如何在表视图中的UITableViewCells中使用“自动布局”,让每个单元格的内容和子视图确定行高度(自身/自动),同时保持平滑的滚动性能?


当前回答

像@Bob Spryn一样,我遇到了一个非常重要的问题,我把这个问题作为答案发布。

我纠结于@smileyborg的回答了一会儿。我遇到的问题是,如果您在IB中使用其他元素(UILabels、UIButtons等)定义了原型单元,当您使用[[YourTableViewCellClass alloc]init]实例化该单元时,它不会实例化该单元中的所有其他元素,除非您编写了这样做的代码。(我对initWithStyle有过类似的经历。)

要让故事板实例化所有其他元素,请使用[tableView dequeueReusableCellWithIdentifier:@“DoseNeed”](不是[tableView de queueReusable CellWithIdentifier:forIndexPath:],因为这会引起有趣的问题。)执行此操作时,将实例化IB中定义的所有元素。

其他回答

UITableView.automaticDimension可以通过接口生成器设置:

Xcode>情节提要>尺寸检查器

表格视图单元格>行高度>自动

我刚刚遇到一个非常重要的问题,作为回答发布。

@smileyborg的回答基本正确。但是,如果自定义单元格类的layoutSubviews方法中有任何代码,例如设置preferredMaxLayoutWidth,则不会使用以下代码运行:

[cell.contentView setNeedsLayout];
[cell.contentView layoutIfNeeded];

这让我困惑了一阵子。然后我意识到这是因为它们只触发contentView上的layoutSubview,而不是单元格本身。

我的工作代码如下:

TCAnswerDetailAppSummaryCell *cell = [self.tableView dequeueReusableCellWithIdentifier:@"TCAnswerDetailAppSummaryCell"];
[cell configureWithThirdPartyObject:self.app];
[cell layoutIfNeeded];
CGFloat height = [cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;
return height;

注意,如果您正在创建一个新的单元格,我很确定您不需要调用setNeedsLayout,因为它应该已经设置好了。在保存对单元格的引用的情况下,您可能应该调用它。不管怎样,它都不会造成任何影响。

另一个提示是,如果您使用的是单元格子类,则需要设置preferredMaxLayoutWidth等属性。正如@smileyborg提到的,“您的表视图单元格的宽度尚未固定到表视图的宽度”。这是正确的,如果您在子类中而不是在视图控制器中进行工作,则会遇到麻烦。但是,此时可以使用表格宽度简单地设置单元格框架:

例如,在计算高度时:

self.summaryCell = [self.tableView dequeueReusableCellWithIdentifier:@"TCAnswerDetailDefaultSummaryCell"];
CGRect oldFrame = self.summaryCell.frame;
self.summaryCell.frame = CGRectMake(oldFrame.origin.x, oldFrame.origin.y, self.tableView.frame.size.width, oldFrame.size.height);

(我碰巧缓存了这个特定的单元以供重用,但这无关紧要)。

在我的例子中,填充是因为sectionHeader和sectionFooter的高度,故事板允许我将其更改为最小值1。因此,在viewDidLoad方法中:

tableView.sectionHeaderHeight = 0
tableView.sectionFooterHeight = 0

关于@smileyborg接受的答案,我发现

[cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize]

在某些约束不明确的情况下是不可靠的。最好使用下面UIView上的帮助器类别强制布局引擎计算一个方向上的高度:

-(CGFloat)systemLayoutHeightForWidth:(CGFloat)w{
    [self setNeedsLayout];
    [self layoutIfNeeded];
    CGSize size = [self systemLayoutSizeFittingSize:CGSizeMake(w, 1) withHorizontalFittingPriority:UILayoutPriorityRequired verticalFittingPriority:UILayoutPriorityFittingSizeLevel];
    CGFloat h = size.height;
    return h;
}

其中w:是表视图的宽度

假设您有一个带有子视图的单元格,并且希望该单元格的高度足够高,以包含子视图+填充。

1) 将子视图的底部约束设置为cell.contentView减去所需的填充。不要对单元格或cell.contentView本身设置约束。

2) 将tableView的rowHeight属性或tableView:heightForRowAtIndexPath:设置为UITableViewAutomaticDimension。

3) 将tableView的estimatedRowHeight属性或tableView:estimatedHeightForRowAtIndexPath:设置为高度的最佳猜测。

就是这样。