6

我构建了一个可变高度自定义表单元的UITableView,它们的高度由包含的多行UILabel的大小决定。我已经连接tableView:heightForRowAtIndexPath:委托方法并使用sizeWithFont:constrainedToSize:正确计算最终高度。UITableViewCell帧高度不匹配tableView:heightForRowAtIndexPath:

我遇到了一个奇怪的问题:在调用数据源方法tableView:cellForRowAtIndexPath:时,正确的每行高度已经按上述方法确定,但单元格的框架与该高度不匹配。相反,单元格的frame.size.height属性是表视图的默认单元高度(86像素,因为我在界面生成器中设置它,正确的高度,当包含的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的是做幕后,离队不设置单元格的边框属性以匹配计算的高度。这本身并不令人惊讶,它将自己的细胞实例排除在外,而不是它们的几何形状。虽然单元格的渲染正确,所以高度属性设置为某处,但它发生在cellForRowAtIndexPath:之后。

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

在此之后,我可以随意滚动表格视图,高度属性从该点开始对每个单元保持正确。

在任何基于出队的重用发生之前,第一次获得正确的单元高度的正确方法是什么?我需要这个来重新定位表格单元格的子视图。我是否需要在cellForRowAtIndexPath:中手动拨打heightForRowAtIndexPath:,然后手动将新创建的CustomCell实例的框架设置为与该高度相匹配?这似乎是多余的,我需要创建一种机制来检测细胞何时以错误的框架高度进行检测,以及何时以正确的框架高度将其排出,以避免这种冗余。因此,如果有人能够阐明这背后的逻辑是什么,我会很感激。

回答

6

正如Flexo所建议的,自己回答这个问题显然比添加编辑问题更好。所以,这是以前的编辑作为答案:


没关系,我应该更好地阅读文档。我可以在tableView:willDisplayCell:forRowAtIndexPath:方法UITableViewDelegate中获得正确的框架,因此这是进行子视图定制的正确位置,它依赖于正确的框架设置,而不是cellForRowAtIndexPath:

有趣的是,文档说这一点,虽然:

delegate返回后,表视图只设置alphaframe属性,然后只有当动画行,因为他们在或滑出。

...因为调用此委托方法时正确的框架已经存在。但无论如何,问题解决了。

+0

最初的问题确实不错,但是这个答案不是很好。分享你如何解决问题? – botbot 2014-12-28 10:42:13

0

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

0

我发现的最简单的方法就是在对单元进行任何设置之前调用cell.layoutIfNeeded()。这确保了所有布局约束条件都被计算出来并且帧被设置。