自从我发现AutoLayout我到处都在用它,现在我正试着把它用在tableHeaderView上.

我做了一个subclass页的UIView页,添加了所有内容(标签等)我想知道他们的限制,然后我把这个CustomView加到UITableView'tableHeaderView.

一切正常,除了UITableView总是显示aboveCustomView,我的意思是CustomViewunderUITableView,所以它看不见!

似乎不管我怎么做,UITableViewtableHeaderViewheightalways0(宽度、x和y也是).

我的问题是:到底有没有可能实现这without setting the frame manually个目标呢?

EDIT : 我使用的CustomViewsubview有这些限制:

_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",因为手动编写约束需要花费很长时间,而且一个约束的行数太多,但是这些方法是self 解释的.

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个"title"的约束决定的.

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

推荐答案

我问并回答了一个类似的问题here.总而言之,我添加了一次页眉,然后使用它来查找所需的高度.然后可以将该高度应用于页眉,并第二次设置页眉以反映更改.

- (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:

- (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)
    }
}

Update January 2015

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

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

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

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)

Ios相关问答推荐

SwiftUI SF Symbols图像:暗模式图像

IFrame内容拒绝仅在iOS浏览器上加载-即使发布了内容-安全-策略(CSP)框架-祖先指令

ios PWA从外部链接返回后降低了innerheight

IOS:在UI线程中执行代码的闭包样式的替代

SwiftUI Divider过大了其父视图

如何以编程方式触发 SwiftUI DatePicker?

在 SwiftUI 中重构提取到子视图的 GeometryReader 代码

在标签中显示多个计数器但在同一屏幕(Swift,IOS)

如何让替换视图淡入旧视图而不是交叉淡入淡出?

视图之间的 SwiftUI 过渡,没有过渡

Swiftui为什么在点击第二行之前背景不起作用

按钮在 SwiftUI 中没有采用给定的高度和宽度

通过MatchedGeometryEffect向上滑动视图

如何关闭情节提要弹出框

从 NSUserDefaults 字典 iOS 中删除所有键

@IBDesignable 崩溃代理

如何更改uitableview删除按钮文本

为什么 Xcode 4 不创建任何产品?

从 UIScrollview 中删除内容和框架布局指南

什么是强属性属性