7

我正在构建一个具有可变高度自定义表格单元格的 UITableView,它们的高度由包含的多行 UILabel 的大小决定。我已经tableView:heightForRowAtIndexPath:连接了委托方法并使用sizeWithFont:constrainedToSize:.

我遇到了一个奇怪的问题:在tableView:cellForRowAtIndexPath:调用数据源方法时,已经如上所述确定了正确的每行高度,但是单元格的框架与该高度不匹配。相反,frame.size.height单元格的属性是表格视图的默认单元格高度(86 px,正如我在 Interface Builder 中设置的那样,包含的 UILabel 只有一行文本时的正确高度),而不是高度确定tableView:heightForRowAtIndexPath:该索引路径的正确性。

我正在cellForRowAtIndexPath:使用出队来生产单元格,也就是说,

// Using storyboards, this never returns nil, no need to check for it
CustomCell *cell = (CustomCell *)[tableView dequeueReusableCellWithIdentifier:@"SomeIdentifier"];
NSLog(@"%f", cell.frame.size.height); // 86, not correct if the cell contains a multi-line UILabel

那么,无论 iOS 在幕后做什么,出队似乎都没有设置单元格的 frame 属性以匹配计算的高度。这本身并不令人惊讶,出队关注的是单元格实例,而不是它们的几何形状。但是,单元格被正确渲染,因此 height 属性被设置在某处,但它发生在cellForRowAtIndexPath:.

所以:当我最初填充表格视图时,cell.frame.size.height所有单元格都是 86,因为它们在我向下滚动列表时第一次出现。由于正确的几何图形是在cellForRowAtIndexPath:每行显示之前的第一个之后的某个时间设置的,因此当我向上滚动时,height 属性对于重用后返回视图的每个单元格都是正确的。

在此之后,我可以随意来回滚动表格视图,并且从那时起,每个单元格的高度属性保持正确。

在任何基于出队的重用发生之前,第一次获得正确单元格高度的正确方法是什么?我需要这个来重新定位表格单元格的子视图。我是否需要手动调用heightForRowAtIndexPath:cellForRowAtIndexPath:然后手动设置新创建的 CustomCell 实例的框架以匹配该高度?这似乎是多余的,我需要创建一种机制来检测第一次创建单元时帧高度错误的时间与稍后以正确帧高度出列的时间,以避免这种冗余。

因此,如果有人可以阐明这背后的逻辑,我将不胜感激。

4

3 回答 3

5

As suggested by Flexo, answering this myself is apparently better than adding an edit to the question. So, here's the previous edit as an answer:


Nevermind, I should read the docs better. I can get the correct frame in the tableView:willDisplayCell:forRowAtIndexPath: method of UITableViewDelegate, so that is the correct place to do subview customization that relies on the correct frame being set, not cellForRowAtIndexPath:.

Interesting that the docs say this, though:

After the delegate returns, the table view sets only the alpha and frame properties, and then only when animating rows as they slide in or out.

...since the correct frame is already there when this delegate method is called. But anyway, problem solved.

于 2012-08-10T13:12:04.700 回答
0

不要忘记单元格是 a UIView,因此覆盖layoutSubviews也是获得正确框架和调整子视图大小/位置的有效方法。只是不要忘记打电话[super layoutSubviews]

于 2014-04-15T07:20:24.957 回答
0

cell.layoutIfNeeded()我发现最简单的方法就是在对单元进行任何设置之前打电话。这可以确保计算所有布局约束并设置框架。

于 2017-04-05T08:19:30.757 回答