当前位置: 首页 > 知识库问答 >
问题:

如何用autolayout设置tableHeaderView (UITableView)的高度?

洪安顺
2023-03-14

在过去的三四个小时里,我一直用这个东西把头撞在墙上,我似乎想不出来。我有一个UIViewController,里面有一个全屏的UITableView(屏幕上还有其他东西,这就是为什么我不能使用UITableViewController的原因),我想让我的tableHeaderView用自动布局调整大小。不用说,这并不合作。

见下面截图。

因为overviewLabel(例如“List overview information here.”文本)有动态内容,所以我使用autolayout调整它的大小,它是superview。我已经很好地调整了所有内容的大小,除了tableHeaderView,它位于层次结构中Paralax表视图的正下方。

我找到的调整标题视图大小的唯一方法是通过编程,使用以下代码:

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

在本例中,headerFrameHeight 是手动计算表视图标题的高度,如下所示(内部标题视图是白色区域,或第二个“视图”,标题视图是表标题视图):

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上有几个关于这个的帖子,但是没有一个是清楚的,最后让我更加困惑。以下是一些例子:

> < Li > < p > UITableViewHeader上的自动布局

表的自动布局标题视图

AutoLayout可以和UITableView的tableHeaderView一起使用吗?

使用自动布局、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中不起作用。但是,它似乎可以在viewWillLayoutSubview中工作。下面的示例代码:

// 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;
}

共有3个答案

诸葛品
2023-03-14

我真的很难做到这一点,把设置放在viewDidLoad中对我来说不管用,因为框架没有在viewDid Load中设置,我还收到了大量杂乱的警告,标题的封装自动布局高度降到了0。我只是在iPad上在Form演示中展示tableView时才注意到这个问题。

对我来说,解决这个问题的方法是在viewWillLayoutSubview中设置tableViewHeader,而不是在viewDidLoad中设置。

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
        }
    }
扈俊健
2023-03-14

我发现了一种使用自动布局来调整表格标题大小的优雅方法,有动画和没有动画。

只需将其添加到视图控制器。

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

和柏
2023-03-14

您需要使用< code > ui view systemLayoutSizeFittingSize:方法来获取标题视图的最小边界大小。

我在本问答中进一步讨论了如何使用此API:

如何调整超级视图的大小以适合具有自动布局的所有子视图?

 类似资料:
  • 我有一个具有动态高度单元格的集合视图(基于可能的多行标签和内部的textview),当我跨越多行时,它在高度上完全适应。但是,当文本只有一个单词或者它没有覆盖整个屏幕宽度时,单元格的宽度正好是所需的宽度,从而导致单元格彼此相邻,而不是在彼此下方。 查看文本视图中具有不同文本长度的结果。 然而,我希望细胞在彼此之下,想想Instagram或Twitter那种视图。显然,我需要为单元格设置一个宽度约束

  • 问题内容: 我有一个奇怪的问题。我试图以编程方式将dataSource分配给表。 我已使用界面生成器在ViewController中为其创建了一个和IBOutlet。我创建了一个实现的类。我将表的设置为dataSource的实例。一切都会编译并正常运行,直到设置dataSource的行在运行时执行。 错误是并且定义线突出显示。 有什么想法为什么我得到这个运行时错误?我正在Swift中使用XCode

  • 我的如下所示,高度设置为40度。 在MyEclipse中,它如下所示: 但是当我在手机上运行它时,它看起来像下面这样: 所以我的问题是为什么进度条的真实高度不是我设置的高度?如何增加进度条的高度?

  • 在页面上我有表,在页面的结尾我有一个段落,如果行包含的行数很少,段落必须仍然停留在页面的结尾,但是如果行数太多且表占用了一个以上的页面,段落必须刚好在表的结尾。一开始这对我来说很容易,我只是为包含表格的PdfPCell设置了最小高度,但后来我发现如果页面被拆分,则最小高度适用于表格的每个部分,因此段落不在第二页的表格下面。有什么解决办法吗?

  • 我有一个大于屏幕高度的tableView,并且有动态调整大小的单元格(UITableViewAutomaticDimension)。我用下面的方法得到了表格视图的高度: 然而,这个高度并不总是正确的,尤其是对于单元格大小大相径庭的长列表。它似乎只是取表的估计高度并将其乘以行数。 如何获得具有不同单元格的tableView的精确高度?

  • 设置为高管保护后,普通成员不能给高管发消息,需由普通成员发起会话申请,高管同意后才可以发消息。 人员管理-人事管理-高管保护-添加-选择需要设置高管保护的成员-确定。 设置了高管保护的成员如需取消,点击“取消高管保护”-确定。