是否可以将 AutoLayout 与 UITableView 的 tableHeaderView 一起使用? [英] Is it possible to use AutoLayout with UITableView's tableHeaderView?

查看:29
本文介绍了是否可以将 AutoLayout 与 UITableView 的 tableHeaderView 一起使用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

自从我发现 AutoLayout 后,我到处使用它,现在我尝试将它与 tableHeaderView 一起使用.

Since I discovered AutoLayout I use it everywhere, now I'm trying to use it with a tableHeaderView.

我创建了一个 UIViewsubclass,添加了我想要的所有内容(标签等...)以及它们的约束,然后我添加了这个 CustomViewUITableView'tableHeaderView.

I made a subclass of UIView added everything (labels etc...) I wanted with their constraints, then I added this CustomView to the UITableView'tableHeaderView.

一切都很好,除了 UITableView 总是显示 above CustomViewabove 我的意思是 CustomView UITableView 之下,所以它不能被看到!

Everything works just fine except the UITableView always displays above the CustomView, by above I mean the CustomView is under the UITableView so it can't be seen !

看来无论我做什么,UITableView'tableHeaderViewheight 都是总是 0(宽度、x 和 y 也是如此).

It seems that no matter what I do, the height of the UITableView'tableHeaderView is always 0 (so is the width, x and y).

我的问题:是否有可能在不手动设置框架的情况下实现这一点?

My question : is it possible at all to accomplish this without setting the frame manually ?

我正在使用的 CustomView'subview 具有以下约束:

EDIT : The CustomView'subview that I'm using has these constraints :

_title = [[UILabel alloc]init];
_title.text = @"Title";
[self addSubview:_title];
[_title keep:[KeepTopInset rules:@[[KeepEqual must:5]]]]; // title has to stay at least 5 away from the supperview Top
[_title keep:[KeepRightInset rules:@[[KeepMin must:5]]]];
[_title keep:[KeepLeftInset rules:@[[KeepMin must:5]]]];
[_title keep:[KeepBottomInset rules:@[[KeepMin must:5]]]];

我正在使用一个方便的库KeepLayout",因为手动编写约束需要永远并且单个约束的行太多,但方法是不言自明的.

I'm using a handy library 'KeepLayout' because writing constraints manually takes forever and way too many line for one single constraint but the methods are self-explaining.

UITableView 有这些限制:

_tableView = [[UITableView alloc]init];
_tableView.translatesAutoresizingMaskIntoConstraints = NO;
_tableView.delegate = self;
_tableView.dataSource = self;
_tableView.backgroundColor = [UIColor clearColor];
[self.view addSubview:_tableView];
[_tableView keep:[KeepTopInset rules:@[[KeepEqual must:0]]]];// These 4 constraints make the UITableView stays 0 away from the superview top left right and bottom.
[_tableView keep:[KeepLeftInset rules:@[[KeepEqual must:0]]]];
[_tableView keep:[KeepRightInset rules:@[[KeepEqual must:0]]]];
[_tableView keep:[KeepBottomInset rules:@[[KeepEqual must:0]]]];

_detailsView = [[CustomView alloc]init];
_tableView.tableHeaderView = _detailsView;

不知道要不要直接在CustomView上设置一些约束,我觉得CustomView的高度是由UILabel上的约束决定的"标题"在其中.

I don't know if I have to set some constraints directly on the CustomView, I think the height of the CustomView is determined by the constraints on the UILabel "title" in it.

EDIT 2: 经过另一次调查似乎正确计算了 CustomView 的高度和宽度,但是 CustomView 的顶部仍然与 UITableView 的顶部处于同一水平并且它们移动当我滚动时一起.

EDIT 2: After another investigation it seems the height and width of the CustomView are correctly calculated, but the top of the CustomView is still at the same level than the top of the UITableView and they move together when I scroll.

推荐答案

我在这里提出并回答了一个类似的问题.总之,我添加了一次标题并使用它来查找所需的高度.然后可以将该高度应用于标题,并再次设置标题以反映更改.

I asked and answered a similar question here. In summary, I add the header once and use it to find the required height. That height can then be applied to the header, and the header is set a second time to reflect the change.

- (void)viewDidLoad
{
    [super viewDidLoad];

    self.header = [[SCAMessageView alloc] init];
    self.header.titleLabel.text = @"Warning";
    self.header.subtitleLabel.text = @"This is a message with enough text to span multiple lines. This text is set at runtime and might be short or long.";

    //set the tableHeaderView so that the required height can be determined
    self.tableView.tableHeaderView = self.header;
    [self.header setNeedsLayout];
    [self.header layoutIfNeeded];
    CGFloat height = [self.header systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;

    //update the header's frame and set it again
    CGRect headerFrame = self.header.frame;
    headerFrame.size.height = height;
    self.header.frame = headerFrame;
    self.tableView.tableHeaderView = self.header;
}

如果你有多行标签,这也依赖于自定义视图设置每个标签的 preferredMaxLayoutWidth:

If you have multi-line labels, this also relies on the custom view setting the preferredMaxLayoutWidth of each label:

- (void)layoutSubviews
{
    [super layoutSubviews];

    self.titleLabel.preferredMaxLayoutWidth = CGRectGetWidth(self.titleLabel.frame);
    self.subtitleLabel.preferredMaxLayoutWidth = CGRectGetWidth(self.subtitleLabel.frame);
}

或者更一般地说:

override func layoutSubviews() {
    super.layoutSubviews()  
    for view in subviews {
        guard let label = view as? UILabel where label.numberOfLines == 0 else { continue }
        label.preferredMaxLayoutWidth = CGRectGetWidth(label.frame)
    }
}

2015 年 1 月更新

不幸的是,这似乎仍然是必要的.这是布局过程的快速版本:

Update January 2015

Unfortunately this still seems necessary. Here is a swift version of the layout process:

tableView.tableHeaderView = header
header.setNeedsLayout()
header.layoutIfNeeded()
header.frame.size = header.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize)
tableView.tableHeaderView = header

我发现将其移动到 UITableView 的扩展中很有用:

I've found it useful to move this into an extension on UITableView:

extension UITableView {
    //set the tableHeaderView so that the required height can be determined, update the header's frame and set it again
    func setAndLayoutTableHeaderView(header: UIView) {
        self.tableHeaderView = header
        self.tableHeaderView?.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activate([
            header.widthAnchor.constraint(equalTo: self.widthAnchor)
        ])
        header.setNeedsLayout()
        header.layoutIfNeeded()
        header.frame.size =  header.systemLayoutSizeFitting(UIView.layoutFittingCompressedSize)
        self.tableHeaderView = header
    }
}

用法:

let header = SCAMessageView()
header.titleLabel.text = "Warning"
header.subtitleLabel.text = "Warning message here."
tableView.setAndLayoutTableHeaderView(header)

这篇关于是否可以将 AutoLayout 与 UITableView 的 tableHeaderView 一起使用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆