重新加载单元格高度变化的单元格时,UITableView 滚动到顶部

Posted

技术标签:

【中文标题】重新加载单元格高度变化的单元格时,UITableView 滚动到顶部【英文标题】:UITableView scrolls to top when reloading cells with changing cell heights 【发布时间】:2015-09-02 20:47:22 【问题描述】:

我有一个表格视图,它在加载图像时包含一个占位符。加载图像时,我调用reloadRowsAtIndexPaths:withRowAnimation:。此时,单元格会根据图像的大小改变高度。发生这种情况时,我希望表格视图的内容偏移保持在原位,并让下面的单元格被进一步向下推,正如您可能想象的那样。

我得到的效果是滚动视图滚动回顶部。我不确定为什么会这样,而且我似乎无法阻止它。将beginUpdates() 放在reloadRows 行之前和endUpdates() 之后没有效果。

我正在使用estimatedRowHeight,因为我的表格视图可能有数百行不同高度的行。我也在执行tableView:heightForRowAtIndexPath:

编辑:我已经建立了一个演示项目来对此进行测试,并且不可否认我无法让演示项目重现这种效果。我会继续努力的。

【问题讨论】:

您能否发布用于获取 tableview 的内容偏移量并设置您希望 tableview 的焦点保持在哪里的代码? 【参考方案1】:

这是estimatedRowHeight 的问题。

estimatedRowHeight 与实际高度的差异越大,重新加载时表格可能会跳得越多,尤其是向下滚动的地方越多。这是因为表格的估计大小与其实际大小完全不同,迫使表格调整其内容大小和偏移量。

最简单的解决方法是使用非常准确的估算值。如果每行的高度变化很大,请确定一行的中间高度,并将其用作估计值。

【讨论】:

在我的测试中,我尝试了一个非常小的估计值和一个非常大的估计值,但都没有产生不必要的滚动效果。 这是一个很好的答案。谢谢你。估计高度不应该是随机数,而是接近您认为的高度。 我使用了估计大小的调整单元格(我猜哪种违背了 UITableViewAutomaticDimension 的目的?)。它为我解决了这个问题。这是因为我的单元格的大小变化很大(根据用户在嵌入的 UITextViews 中键入的内容)【参考方案2】:

始终主线程上更新 UI。所以只需放置

[self.tableView reloadData];

在主线程内:

dispatch_async(dispatch_get_main_queue(), ^
     //UI Updating code here.
     [self.tableView reloadData];
);

【讨论】:

在主线程中执行重新加载如何影响滚动到顶部?【参考方案3】:

我遇到了同样的问题并通过这种方式决定:在加载时保存单元格的高度并在tableView:estimatedHeightForRowAtIndexPath中给出确切的值:

// declare cellHeightsDictionary
NSMutableDictionary *cellHeightsDictionary;

// save height
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath 
    [cellHeightsDictionary setObject:@(cell.frame.size.height) forKey:indexPath];


// give exact height value
- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath 
    NSNumber *height = [cellHeightsDictionary objectForKey:indexPath];
    if (height) return height.doubleValue;
    return UITableViewAutomaticDimension;

【讨论】:

就我而言,我在超类中有self.tableView.estimatedRowHeight = 44;。在当前类中将其设置为零,我有固定的行高解决了这个问题。【参考方案4】:

我看到了这一点,对我有用的解决方法是选择可能行中最小的估计行高。当意外滚动发生时,它最初被设置为最大可能的行高。我只是使用单个 tableView.estimatedRowHeight 属性,而不是委托方法。

【讨论】:

以上是关于重新加载单元格高度变化的单元格时,UITableView 滚动到顶部的主要内容,如果未能解决你的问题,请参考以下文章

如何在使用tableViews自定义单元格时在运行时更改表视图单元格高度?

重新加载 UITableView 而不重新加载标题部分

显示更多按钮操作的动态标签和单元格高度

动画 UICollectionView 单元格大小更改和重新定位周围的单元格

删除高度大于其他单元格的单元格时,动画看起来很尴尬

UITableView rowHeight UITableViewAutomaticDimension 首次加载后单元格高度错误