问题 - 如何最好地计算 UITableViewController 的“heightForRowAtIndexPath”方法中一行的高度,假设:
- 我正在使用自定义子类 UITableViewCell ,子视图的实际大小(例如 UILabels)是在运行时计算的,并且取决于用户是否更改字体大小等因素
- 在“heightForRowAtIndexPath”之前,单元格实际上并未准备好,因此您不能依赖调用特定的自定义单元格实例来查询它
目前我唯一能想到的就是:
1. 在您的自定义 UITableViewCell 子类中创建一个方法来计算 UITableViewCell 子类中每个子视图(例如 UILabel)的高度 - 然后在创建实例时在单元格子类中使用它
2. 另外,在自定义子类中创建一个贯穿所有 UILabels 的类方法,调用上述方法来总结高度,从而计算出总行高。它必须获取传递给它的数据(例如每个 UILabels 中的文本)
3. 在 UITableViewController“heightForRowAtIndexPath”中,您必须调用上面 (2) 中的“calRowHeight”类型方法,并向其传递标签文本数据。因此,有效地调用自定义单元格子类上的类方法,该方法知道如何计算总行高,但它也使用单元格所需的相同逻辑......
还有比我缺少的更简单的方法吗?
创建 UITableView 时,每当您向其发送 reloadData 消息时,都会向数据源发送每个单元格的 heightForRowAtIndexPath 消息。因此,如果您的表格有 30 个单元格,则该消息将发送 30 次。
假设这 30 个单元格中只有 6 个在屏幕上可见。在这种情况下,当创建时并向其发送 reloadData 消息时,UITableView 将为每个可见行发送一个 cellForRowAtIndexPath 消息,即该消息被发送六次。
苹果为什么要这样实现呢?部分原因是计算行的高度几乎总是比构建和填充整个单元格更便宜。鉴于在许多表格中每个单元格的高度都是相同的,因此它通常要便宜得多。部分原因是 iOS 需要知道整个表格的大小:这允许它创建滚动条并将其设置在滚动视图等上。
如果行高大小因包含不同数量的文本而变化,则可以对相关字符串使用 sizeWithFont: 方法之一来进行计算。这比构建视图然后测量结果更快。请注意,如果更改单元格的高度,则需要重新加载整个表格(使用 reloadData - 这将询问委托的每个高度,但仅询问可见单元格)或有选择地重新加载大小已改变的行改变了。
附加材料如果我理解评论中的后续问题,以下内容可能会有所帮助:
如果您正在实现编辑模式,那么需要更改表格行的高度并不罕见。例如,您的表格行中可能有文本,当它们的单元格变窄时(为了为右侧的删除圆圈腾出空间),您可能希望某些单元格变高以容纳文本。这里的基本方法是:
确保 tableView:heightForRowAtIndexPath: 方法知道您是否处于编辑模式。 (它可以使用 isEditing 询问 tableView。)然后获取返回正确高度的方法,具体取决于您是否处于编辑模式。
在 UITableViewController 中的 setEditing:animated: 方法中(或 UIViewController,无论您使用哪个 - 根据您使用的不同,存在一些差异,因此值得仔细检查文档)在更改其状态后向 tableView 发送 reloadData 消息。这将强制 tableView 获取每一行的高度,并将重新获取可见行的单元格。当您进入编辑模式时,tableView 会处理使单元格变窄,但如果您想在布局上做更多工作,请在 tableView:cellForRowAtIndex: 中进行。如上所述,总体策略是找到一种快速计算高度的方法。使用文本 sizeWithFont: (及其变体)可以做到这一点。如果您有图像等,那么您可以获取它们的尺寸并进行一些求和。
-
除了这些步骤之外,您可能还想在切换模式后稍微滚动 tableView。如果行的高度不同,那么切换模式后您将在表格中处于错误的位置。我在这里采取的方法是在重新加载表后使用 PerformSelector:withObject:afterDelay 来调用执行滚动调整的方法。您需要使用延迟,以便 tableView 有时间收集新的高度和新的表格单元格。 (可能有一种更聪明的方法。)我根据重新加载之前和之后屏幕上单元格第一个可见行的 tableView:cellForRowAtIndexPath: 的 origin.y 之间的差异进行一些求和,以进行滚动调整。因此,例如,要获取预加载之前的位置,有点像这样。
CGPoint offset = [[self tableView] contentOffset];
NSIndexPath* indexPath = [[self tableView] indexPathForRowAtPoint:CGPointMake(0,offset.y)];
CGFloat preCellOffset = [[[self tableView] cellForRowAtIndexPath:indexPath] origin].y;
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)