我有一个表视图,每个单元格可能有自己的高度,因此不适合使用rowHeight
。相反,我现在正在使用let indexSet = NSIndexSet(index: 10)
和self.tableView.estimatedRowHeight = 75
。这意味着它调用单元格上的sizeThatFits
函数,以确定其高度。这一切都运作良好。
当您重新加载屏幕上的单元格时,问题就出现了。例如,向下滚动以显示单元格10,然后重新加载单元格10,工作正常。但是当你开始向上滚动,经过你已经看过的单元格时,它会恢复到每个单元格的estimatedRowHeight,完全忽略sizeThatFits
,因此在滚动时跳转。我不可能给出一个准确或“足够好”的估计值,因此这种跳跃不会引人注意,因为我的细胞能够显示一行文字或一个完整的图像 - 这是一个很大的区别。大小
我在这里看到了这个效果:
我在这方面做了很多不同的尝试,使用了heightForRowAtIndexPath,estimatedHeightForRowAtIndexPath等的混合物。我在StackOverflow上尝试了各种建议。似乎没什么用。
我附上了一个非常简单的示例项目,您可以自己尝试:
https://www.dropbox.com/s/8f1rvkx9k23q6c1/tableviewtest.zip?dl=0
值得注意的是 - 如果单元格在重新加载时不在视图中,则会发生 not 。如果它位于当前滚动点下方的或之上,则一切都按预期工作。
答案 0 :(得分:17)
这种行为似乎是一个错误,如果没有其他原因,它在iOS 9上不再可复制。我确定没有太多的安慰。
这个问题主要源于估计不准确,如@NickCatib所说。你可以在iOS 8上做的最好的事情就是改进估算。许多人建议的技术是在willDisplayCell
中缓存高度,并在后续调用estimatedRowHeightAtIndexPath
时使用它们。
您可以通过不做任何让UITableView
丢弃其缓存的操作来缓解行为,例如直接使用cellForRowAtIndexPath
修改单元格中的内容,而不是使用重新加载{39}。 ;在屏幕上。但是,如果您确实需要更改单元格的高度,那将无济于事。
我不敢说错误无法在桌面视图中轻松修复,因为您无法控制布局。通过在失效期间更改UICollectionViewFlowLayout
,可以更轻松地在子类contentOffsetAdjustment
中解决该错误,尽管这可能不是非常容易。
答案 1 :(得分: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;
}
}
答案 2 :(得分:2)
在iOS 13.5.1中:
我有一个tableView,其中包含4种类型的单元格,所有单元格具有不同的动态高度。 我在这里遵循了公认的解决方案,但是要解决跳跃效果,我需要在重新加载表格视图时添加更多内容:
从接受的答案中,我添加了以下代码: 声明此变量
var allCellHeights = [IndexPath : CGFloat]()
然后添加2种方法:
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
self.allCellHeights[indexPath] = cell.frame.size.height
}
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
return self.allCellHeights[indexPath] ?? UITableView.automaticDimension
}
现在,我在重新加载tableview时必须添加的额外代码:
let contentOffset = self.tableView.contentOffset
self.tableView.reloadData()
self.tableView.layoutIfNeeded()
self.tableView.setContentOffset(contentOffset, animated: false)
还要检查此答案:reloadData() of UITableView with Dynamic cell heights causes jumpy scrolling
答案 3 :(得分:0)
我们来看看facebook吧。他们的时间表也存在同样的问题,他们最终在某种网络视图中做到了。
我在某种时间轴上遇到了类似的问题,使用了自动行高并遇到了这个问题。解决它的第一件事是将estimatedHeight
设置为尽可能接近平均细胞高度。这很难处理,因为你可能有文字(高50)或图像+文字(高1500)。接下来要改进的是实现estimatedHeight forIndexPath
,它基本上为不同的indexPath返回不同的估计高度。
之后还有很多其他的解决方案,但这个方案尽可能接近可变高度(差异很大)。
答案 4 :(得分:-2)
我遇到了同样的问题,我的表工作正常,直到tableview重新加载。所以我找到了一个解决方案,只使用rowHeight而不是估计的高度。如果你有不同的身高。所以请提供完整的代码,以便我提供解决方案。我有一个像Instagram页面的单元格。我通过计算高度的heightforrow方法工作正常。但在这种情况下,估计的身高不会很好。如果你使用下面的代码,它工作正常。请试试。
self.tableView.rowHeight = 75 //it will be your dynamic height
//self.tableView.estimatedRowHeight = 75
如果您混淆计算每个单元格的行高,只需发布样本我将提供解决方案。如果我能 谢谢