如何使用自动布局设置tableHeaderView(UITableView)的高度?

在过去的3到4个小时里,我一直在用这种方式将我的头撞在墙上,我似乎无法弄清楚。 我有一个UIViewController里面有一个全屏UITableView(屏幕上还有一些其他的东西,这就是为什么我不能使用UITableViewController),我想让我的tableHeaderView通过自动布局调整大小。 不用说,这不合作。

见下面的截图。

在这里输入图像描述

因为overviewLabel(例如“List overview information here”文本)具有动态内容,所以我使用autolayout来调整它的大小并且它是超级视图。 我已经调整好了所有的东西,除了tableHeaderView,它恰好位于hiearchy中的Paralax Table 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的文章,但没有一篇很清楚,最终让我更加困惑。 这里有几个:

  • 在UITableViewHeader上自动布局

  • tableHeaderView的自动布局

  • 有没有可能与UITableView的tableHeaderView使用AutoLayout?

  • 使用自动布局,IB和字体大小时,表格标题视图高度错误

  • 将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:正如其他人所指出的,编辑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:方法来获取您的标题视图的最小边界大小。

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

    如何调整superview以适应所有子视图和自动布局?


    我真的与这一战斗,并将设置放入viewDidLoad不适合我,因为框架没有设置在viewDidLoad中,我也结束了大量凌乱的警告,其中标题的封装自动布局高度降低为0我只在桌面演示文稿中呈现tableView时才注意到iPad上的问题。

    什么解决了我的问题是在viewWillLayoutSubviews而不是在viewDidLoad中设置tableViewHeader。

    func viewWillLayoutSubviews() {
            super.viewWillLayoutSubviews()
            if tableView.tableViewHeaderView == nil {
                let header: MyHeaderView = MyHeaderView.createHeaderView()
                header.setNeedsUpdateConstraints()
                header.updateConstraintsIfNeeded()
                header.frame = CGRectMake(0, 0, CGRectGetWidth(tableView.bounds), CGFloat.max)
                var newFrame = header.frame
                header.setNeedsLayout()
                header.layoutIfNeeded()
                let newSize = header.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize)
                newFrame.size.height = newSize.height
                header.frame = newFrame
                self.tableView.tableHeaderView = header
            }
        }
    

    我发现了一种优雅的方式来使用自动布局来调整表头的大小,使用和不使用动画。

    只需将其添加到您的View Controller。

    func sizeHeaderToFit(tableView: UITableView) {
        if let headerView = tableView.tableHeaderView {
            let height = headerView.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize).height
            var frame = headerView.frame
            frame.size.height = height
            headerView.frame = frame
            tableView.tableHeaderView = headerView
            headerView.setNeedsLayout()
            headerView.layoutIfNeeded()
        }
    }
    

    根据动态变化的标签调整大小:

    @IBAction func addMoreText(sender: AnyObject) {
        self.label.text = self.label.text! + "nThis header can dynamically resize according to its contents."
    }
    
    override func viewDidLayoutSubviews() {
        // viewDidLayoutSubviews is called when labels change.
        super.viewDidLayoutSubviews()
        sizeHeaderToFit(tableView)
    }
    

    根据约束条件的变化来动态调整大小:

    @IBOutlet weak var makeThisTallerHeight: NSLayoutConstraint!
    
    @IBAction func makeThisTaller(sender: AnyObject) {
    
        UIView.animateWithDuration(0.3) {
            self.tableView.beginUpdates()
            self.makeThisTallerHeight.constant += 20
            self.sizeHeaderToFit(self.tableView)
            self.tableView.endUpdates()
        }
    }
    

    查看AutoResizingHeader项目以查看这个实际操作。 https://github.com/p-sun/Swift2-iOS9-UI

    AutoResizingHeader

    链接地址: http://www.djcxy.com/p/28277.html

    上一篇: How do I set the height of tableHeaderView (UITableView) with autolayout?

    下一篇: UITextView offsets text differently than UILabel