重新加载单元格后向上滚动时,动态单元格高度跳跃的UITableView

问题描述 投票:14回答:4

我有一个表格视图,每个单元格有可能有自己的高度,因此不适合使用rowHeight。相反,现在我正在使用let indexSet = NSIndexSet(index: 10)self.tableView.estimatedRowHeight = 75。这意味着它调用单元格上的sizeThatFits函数,以确定其高度。这一切都运作良好。

问题是当你重新加载屏幕上的单元格时。例如,向下滚动以显示单元格10,然后重新加载单元格10,工作正常。但是当你开始向上滚动,经过你已经看过的细胞时,它会恢复到每个细胞的estimatedRowHeight,完全忽略sizeThatFits,所以当你滚动时跳转。我不可能给出一个准确或“足够好”的估计值,因此这种跳跃不会引人注意,因为我的细胞能够显示一行文字或一个完整的图像 - 这是一个很大的区别。尺寸。

我在这里展示了这个效果:

https://vid.me/edgW

我在这方面做了很多不同的尝试,使用了heightForRowAtIndexPath,estimatedHeightForRowAtIndexPath等的混合物。我在StackOverflow上尝试了各种建议。似乎没什么用。

我附上了一个非常简单的示例项目,您可以自己尝试:

https://www.dropbox.com/s/8f1rvkx9k23q6c1/tableviewtest.zip?dl=0

  1. 运行该项目。
  2. 滚动,直到查看单元格10。
  3. 等待最多5秒钟让细胞重新加载(它变成紫色)。
  4. 向上滑动。

值得注意的是 - 如果单元格在重新加载时不在视图中,则不会发生这种情况。如果它高于或低于当前滚动点,则一切都按预期工作。

ios objective-c swift uitableview
4个回答
17
投票

这种行为似乎是一个错误,如果没有其他原因,它不再可以在iOS 9上重现。我敢肯定,这不是什么安慰。

这个问题主要来自于一个不准确的估计,如@NickCatib所说。你可以在iOS 8上做的最好的事情就是改进估算。许多人推荐的技术是在willDisplayCell中缓存高度,并在随后调用estimatedRowHeightAtIndexPath时使用它们。

您可以通过不执行任何操作来缓解行为,以使UITableView丢弃其缓存,例如通过使用cellForRowAtIndexPath直接修改单元格中的内容而不是使用重新加载(如果它在屏幕上)。但是,如果您确实需要更改单元格的高度,那将无济于事。

我不敢说在桌面视图中不能轻易修复bug,因为你无法控制布局。通过在失效期间更改UICollectionViewFlowLayout,可以更容易地在子类contentOffsetAdjustment中处理该错误,尽管这可能不是非常容易。


11
投票

我也有这个问题,并使用了SO的解决方案,我现在无法找到。如果我这样做,我会添加链接。这是解决方案:

问题是表格视图没有正确的行高估计。要修复它,最初在willDisplayCell中缓存高度,然后再使用该高度。

在viewDidLoad中:

heightAtIndexPath = [NSMutableDictionary new];


- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
    NSNumber *height = @(cell.frame.size.height);
    [heightAtIndexPath setObject:height forKey:indexPath];
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
    return UITableViewAutomaticDimension;
}

- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath{
    if([heightAtIndexPath objectForKey:indexPath]) {
        return [[heightAtIndexPath objectForKey:indexPath] floatValue];
    } else {
        return UITableViewAutomaticDimension;
    }
}

0
投票

呃......这是一个很难处理的问题。

我们来看看facebook吧。他们的时间表也有同样的问题,他们最终在某种网络视图中做到了这一点。

我在某种时间轴上遇到了类似的问题,使用了自动行高并且遇到了这个问题。解决它的第一件事是将estimatedHeight设置为尽可能接近平均细胞高度。这很难处理,因为你可能有文字(高50)或图像+文字(高1500)。接下来要改进的是实现estimatedHeight forIndexPath,它基本上为不同的indexPath返回不同的估计高度。

在那之后还有很多其他的解决方案,但这是最接近它的可变高度(巨大的差异)。


-2
投票

我遇到了同样的问题,我的表工作正常,直到tableview重新加载。所以我找到了一个解决方案,只使用rowHeight而不是估计的高度。如果你有不同的身高。所以请提供完整的代码,以便我提供解决方案。我有一个像Instagram页面的单元格。我通过计算高度的heightforrow方法工作正常。但在这种情况下,估计的身高不会很好。如果你使用下面的代码,它工作正常。请试试。

self.tableView.rowHeight = 75 //it will be your dynamic height
//self.tableView.estimatedRowHeight = 75

如果您混淆计算每个单元格的行高,只需发布​​样本我将提供解决方案。如果我能谢谢

© www.soinside.com 2019 - 2024. All rights reserved.