最近3到4个小时,我一直在用头撞墙,但似乎无法解决。我有一个带有全屏UITableView的UIViewController(屏幕上还有其他一些东西,这就是为什么我不能使用UITableViewController的原因),并且我想让tableHeaderView可以通过自动布局来调整大小。不用说,它没有合作。

请参见下面的屏幕截图。

因为overviewLabel(例如“此处列出概述信息。”文本)具有动态内容,所以我正在使用自动布局来调整其大小,并成为其 super View 。除了tableHeaderView,它一切都很好地调整了大小,tableHeaderView处于层次结构中的Paralax Table View的正下方。

我发现调整标题 View 大小的唯一方法是通过编程,使用以下代码:

CGRect headerFrame = self.headerView.frame;
headerFrame.size.height = headerFrameHeight;
self.headerView.frame = headerFrame;
[self.listTableView setTableHeaderView:self.headerView];

在这种情况下,headerFrameHeight是tableViewHeader高度的手动计算,如下所示(innerHeaderView是白色区域,或者第二个“ View ”,headerView是tableHeaderView):
CGFloat startingY = self.innerHeaderView.frame.origin.y + self.overviewLabel.frame.origin.y;
CGRect overviewSize = [self.overviewLabel.text
                       boundingRectWithSize:CGSizeMake(290.f, CGFLOAT_MAX)
                       options:NSStringDrawingUsesLineFragmentOrigin
                       attributes:@{NSFontAttributeName: self.overviewLabel.font}
                       context:nil];
CGFloat overviewHeight = overviewSize.size.height;
CGFloat overviewPadding = ([self.overviewLabel.text length] > 0) ? 10 : 0; // If there's no overviewText, eliminate the padding in the overall height.
CGFloat headerFrameHeight = ceilf(startingY + overviewHeight + overviewPadding + 21.f + 10.f);

手动计算是可行的,但是如果将来发生变化,它会很笨拙并且容易出错。我要能够做的就是让tableHeaderView根据所提供的约束自动调整大小,就像在其他任何地方一样。但是对于我的一生,我无法弄清楚。

SO上有几篇关于此的文章,但都不清楚,最终使我更加困惑。这里有一些:
  • Auto layout on UITableViewHeader
  • Auto Layout for tableHeaderView
  • Is it possible to use AutoLayout with UITableView's tableHeaderView?
  • table header view height is wrong when using auto layout, IB, and font sizes

  • 将translatesAutoresizingMaskIntoConstraints属性更改为NO并没有任何意义,因为这只会给我带来错误,而且从概念上讲也没有任何意义。

    任何帮助将不胜感激!

    编辑1:
    多亏了TomSwift的建议,我才得以弄清楚。无需手动计算概览的高度,而是可以按照以下方式为我计算概览的高度,然后像以前一样重新设置tableHeaderView。
    [self.headerView setNeedsLayout];
    [self.headerView layoutIfNeeded];
    CGFloat height = [self.innerHeaderView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height + self.innerHeaderView.frame.origin.y; // adding the origin because innerHeaderView starts partway down headerView.
    
    CGRect headerFrame = self.headerView.frame;
    headerFrame.size.height = height;
    self.headerView.frame = headerFrame;
    [self.listTableView setTableHeaderView:self.headerView];
    

    编辑2:如其他人所指出的那样,发布在Edit 1中的解决方案似乎在viewDidLoad中不起作用。但是,它似乎可以在viewWillLayoutSubviews中工作。下面的示例代码:
    // Note 1: The variable names below don't match the variables above - this is intended to be a simplified "final" answer.
    // Note 2: _headerView was previously assigned to tableViewHeader (in loadView in my case since I now do everything programatically).
    // Note 3: autoLayout code can be setup programatically in updateViewConstraints.
    - (void)viewWillLayoutSubviews {
        [super viewWillLayoutSubviews];
    
        [_headerWrapper setNeedsLayout];
        [_headerWrapper layoutIfNeeded];
        CGFloat height = [_headerWrapper systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;
    
        CGRect headerFrame = _headerWrapper.frame;
        headerFrame.size.height = height;
        _headerWrapper.frame = headerFrame;
        _tableView.tableHeaderView = _headerWrapper;
    }
    

    最佳答案

    您需要使用UIView systemLayoutSizeFittingSize:方法来获取标题 View 的最小边界大小。

    我将在此Q/A中提供有关使用此API的进一步讨论:

    How to resize superview to fit all subviews with autolayout?

    10-07 21:07