-systemLayoutSizeFittingSize:在iOS 8下为tableHeaderView返回不正确的高度

Jef*_*wen 24 objective-c uitableview ios

关于正确调整带有自动布局的tableHeaderView(一个这样的线程)有很多线程,但它们倾向于预先设置iOS 8.

我有一个有很多表视图的情况,都有标题,在iOS 7下正确大小但在iOS 8下使用大多数上述线程支持的代码不正确.在表的控制器中,我有以下方法:

- (void)rejiggerTableHeaderView
{
    self.tableView.tableHeaderView = nil;

    UIView *header = self.headerView;

    [header setNeedsLayout];
    [header layoutIfNeeded];

    CGFloat height = [header systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;

    CGRect headerFrame = header.frame;
    headerFrame.size.height = height;

    header.frame = headerFrame;

    self.tableView.tableHeaderView = header;
}
Run Code Online (Sandbox Code Playgroud)

使用iOS 7下的多行标签,这样可以正确调整表格视图的标题大小,如下所示:

但是在iOS 8下运行的相同代码会产生以下结果:

获取-systemLayoutSizeFittingSize的技巧是什么:在iOS 8下返回正确的大小?这是一个演示该问题的示例项目.

Wil*_*mar 17

将headerview函数更改为以下内容适用于我:

- (void)rejiggerTableHeaderView
{
    self.tableView.tableHeaderView = nil;

    UIView *header = self.headerView;
    CGRect frame = header.frame;
    frame.size.width = self.tableView.frame.size.width;
    header.frame = frame;

    [header setNeedsLayout];
    [header layoutIfNeeded];

    CGFloat height = [header systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;

    CGRect headerFrame = header.frame;
    headerFrame.size.height = height;

    header.frame = headerFrame;

    self.tableView.tableHeaderView = header;
}
Run Code Online (Sandbox Code Playgroud)

  • 我发现罪魁祸首是一个缺失的约束:从超级视图的所有4个方向的"UILabel"中获得一个支柱是至关重要的.一个缺少的约束将阻止`systemLayoutSizeFittingSize:UILayoutFittingCompressedSize`正常工作. (5认同)

Vit*_*nko 16

问题可以是非设定的preferredMaxLayoutWidth.如果您将其设置为更正UILabel宽度,它将正确确定约束.

您可以遍历UILabel标题中的所有内容并设置preferredMaxLayoutWidth为标签宽度.

Swift 3示例:

extension UITableView {
    public func relayoutTableHeaderView() {
        if let tableHeaderView = tableHeaderView {
            let labels = tableHeaderView.findViewsOfClass(viewClass: UILabel.self)
            for label in labels {
                label.preferredMaxLayoutWidth = label.frame.width
            }
            tableHeaderView.setNeedsLayout()
            tableHeaderView.layoutIfNeeded()
            tableHeaderView.frame.height = tableHeaderView.systemLayoutSizeFitting(UILayoutFittingCompressedSize).height
            self.tableHeaderView = tableHeaderView
        }
    }

    public func findViewsOfClass<T:UIView>(viewClass: T.Type) -> [T] {
        var views: [T] = []
        for subview in subviews {
            if subview is T {
                views.append(subview as! T)
            }
            views.append(contentsOf: subview.findViewsOfClass(viewClass: T.self))
        }
        return views
    }
}
Run Code Online (Sandbox Code Playgroud)

更新2:

如果您具有纵横比约束的子视图并且同时与超视图宽度约束成比例,则您也可能遇到高度计算错误的问题


Chr*_*s C 6

由于这个问题是一年半的历史,这里是一个更新和完整的版本,在Swift.接受的答案中的一些代码是错误的或过时的.

func fixHeaderHeight() {
    // Set your label text if needed
    // ...
    //

    guard let header = tableView.tableHeaderView else {
        return
    }    
    let height = header.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize).height
    header.frame.height = height            
    tableView.tableHeaderView = header
}
Run Code Online (Sandbox Code Playgroud)

在代码的其他地方,您需要preferredMaxLayoutWidth在标题中设置标签.这应该等于tableView(或屏幕宽度)减去任何填充.didSet您的标签插座的方法是一个好地方:

@IBOutlet weak var headerMessageLabel: UILabel! {
        didSet {
            headerMessageLabel.preferredMaxLayoutWidth = UIScreen.mainScreen().bounds.width - headerMessageLabelPadding
        }
    }
Run Code Online (Sandbox Code Playgroud)

注意:如果接受的答案适合您,则表示您未正确使用大小类.