estimatedHeightForRowAtIndexPath 实际上可以更改行的最终“正确”高度吗?

Posted

技术标签:

【中文标题】estimatedHeightForRowAtIndexPath 实际上可以更改行的最终“正确”高度吗?【英文标题】:estimatedHeightForRowAtIndexPath can in fact change the final "correct" height of a row? 【发布时间】:2013-11-27 09:31:54 【问题描述】:

我刚刚发现了在使用 estimatedHeightForRowAtIndexPath 时的一个令人震惊的问题或违反直觉的行为

(1) 我的桌子的行高变化很大。最终结果的范围从 111 到大约 400。

(2) 我绝对完美地计算了每一行的高度。我手头有这些在一个数组中,也就是说被缓存了。

请注意,这正是 Apple 工程师现在推荐的内容...例如,第 5 点 ..Using Auto Layout in UITableView for dynamic cell layouts & variable row heights

(3) 当 heightForRowAtIndexPath 要求一个高度时,我确实给它绝对正确的高度。

(4) 实际上,当我构建单元时,我会将其构建到完全正确的高度(如 (2) 和 (3) 中所示)。

注意 - 当然最终确定单元格高度大小的是 ios,而不是“我”。

这一切都完美无缺。

也就是说,每个单元格都是由 iOS 在 heightForRowAtIndexPath 中给定的高度构建的。

现在,我添加代码...

-(CGFloat)tableView:(UITableView *)tableView
    estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath 
    return 120;

事实上,表格不再有效........行高变得随机!!!

有人见过这种不可思议的行为吗?

我进行了各种测试,试图确定这到底是什么的估计HeightForRowAtIndexPath 的关系。起初,我认为它可能会提供高度的下限。因此,150 .. 甚至我较小的单元格也会错误地为 150 高度。但事实并非如此。

我认为它可能会做这样的事情:假设您的估计HeightForRowAtIndexPath 值为 150。它有时使用 150 表示行(实际上()证明是该大小或更小,但有时它适用于实际大小heightForRowAtIndexPath。

另一方面,如果您为估计的HeightForRowAtIndexPath 输入的值小于实际存在的值(在我的示例中为 100),那么它几乎“完全行不通”,您只会得到似乎只有单元格上的随机高度。

非常高的单元格似乎可以正常工作,可能类似于“如果 heightForRowAtIndexPath 的高度是估计值的两倍,那么它确实使用实际高度”

需要明确的是,它似乎永远不会使单元格变得太小,但它经常会使它们变得太大。

明确地说,我使用自动布局,这是您必须构建的单元格类型。 (恐怕我不知道这与自动布局有何关系。)这仅适用于 Xcode5/iOS7+。

【问题讨论】:

估计行可能是最大可能高度?你的情况是400。我认为 tableview 委托会发现 tableview 的最大可能大小比这两者之间的最小值或随机值更有用。 不起作用!当我使用一个较大的值(比如 400)时,总之,它会“弄乱更多的行”。同样,如果我使用一个小值(比如 50),它会“弄乱更多行”。对我来说完全神秘。 实际上,如果您设置了一个大得离谱的值(2000),iOS 只是“完全忽略”了估计值,然后每一行都是 heightForRowAtIndexPath 中给出的准确正确高度......我'我不确定。令人震惊和引人入胜的问题!!! 您是说可见行有误,还是只是某些行不在屏幕上? 对,可见行是错误的。 (关于屏幕上没有的行 - 我看不到它们:))如果你尝试一下,你会发现它使高度“完全错误”。 【参考方案1】:

更新答案

经过进一步调查,事实证明“它只需要自动布局”是不正确的。我的示例代码需要自动布局。我在DynamicHeightCell 中做了一点修改,现在可以使用或不使用自动布局。

原答案

它只需要自动布局。这并不奇怪,真的,但绝对应该记录在案。

这是一个工作项目,演示 tableView:estimatedHeightForRowAtIndexPath: 与自动布局一起正常工作。如果您在情节提要中关闭自动布局,它的行为与您描述的一样。

Estimated Row Height Demo

【讨论】:

没问题,乔。谢谢! 呃。 @JoeBlow 我将不得不反驳我自己草率的回答。见更新。请收回积分。 estimatedHeightForRowAtIndexPath 一定有一些副作用会破坏你的实现。我想知道这是否是一个重用问题。最初的屏幕单元格是否正确显示,然后您在滚动时看到错误的行为?你能发布你的高度计算和单元格配置代码吗? “我只是制作了 20 个细胞并使用了那些” 这有点不寻常。我们能看到你的“cellForRowAtIndexPath”和heightForRowAtIndexPath吗? 也许很疯狂的问题,@JoeBlow 和 Timothy Moose:你在哪里加载 UITableView?在viewDidLoadviewDidAppearviewWillAppear?我有类似的东西。更改我的代码以在 viewWillAppear 中加载表格解决了我的问题 - 但我不确定这正是您所遇到的。我使用了NSLog,发现我的estimatedHeightForRowAtIndexPathheightForRowAtIndexPathcellForRowAtIndexPath 以某种奇怪的顺序运行。一旦我移动了加载表格的位置,它就可以正常工作了。【参考方案2】:
- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath  

当您有大量动态单元格时,通常使用此委托方法,它提供了单元格的粗略估计。

例如:如果您有 100 个单元格,每个单元格的高度范围为 200 到 300(例如 201、207、250、299、300...),您可以估计单元格高度约为 250。即

- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath 
return 250;

提供行高估计值可以改善加载表格视图时的用户体验。 如果未实施此委托,则计算其所有高度可能会很昂贵,因此会导致加载时间更长。

【讨论】:

以上是关于estimatedHeightForRowAtIndexPath 实际上可以更改行的最终“正确”高度吗?的主要内容,如果未能解决你的问题,请参考以下文章