我正在使用iOS 7中UITableView的estimatedRowHeight
方法,它非常适合快速加载具有5000行可变高度的UITableView。
我的UITableView包含50个部分。每个部分有100行,高度可变。
在开始时我使用estimatedRowHeight
进行快速加载,但在此之后,当我调用scrollToRowAtIndexPath
时,我的UITableView滚动到错误的偏移量。我可以理解为什么会这样,因为它有一个estimatedRowHeight
,直到我滚动整个表格并在heightForRowAtIndexPath
委托方法中设置了正确的单元格高度。
任何解决方案?
答案 0 :(得分:7)
不幸的是,在使用如此低的值的代码中使用estimatedRowHeight
时会出现此问题。当您scrollToRowAtIndexPath
时,它不会主动计算正确的大小。根本原因是,如果您从第1节滚动到第2节,它可以实时计算正确的位置和单元格的estimatedRowHeight
,如果它是一个相对较新的设备。任何较旧的设备都会被瘫痪,例如,如果你必须处理5000个细胞,那么任何新的设备也会如此。
解决问题的一个可能方法是增加estimatedRowHeight
常数,这样设备就不必做太多的工作。
答案 1 :(得分:2)
当调用scrollToRowAtIndexPath
时,不计算所有单元格的高度b / w当前位置和目标偏移。只有其中一些是。
相反,UITableView使用estimatedRowHeight
来计算导致错误偏移的目标偏移量。
我面临同样的问题,我发现了一个小技巧(我不太喜欢),只能在初始relaodData
之后计算一次精确的细胞高度。我在下面插入两行:
tableView.reloadData()
// only for the initial reloadData
let numSections = tableView.numberOfSections
let numRowsInLastSection = tableView.numberOfRowsInSection(numSections-1)
// scrolls to the last row in the tableView
tableView.scrollToRowAtIndexPath(NSIndexPath(forRow: numRows-1, inSection: numSections-1), atScrollPosition: .Bottom, animated: false)
// back again to the original position(which is 0 for this is only called right after the initial reloadData)
tableView.scrollToRowAtIndexPath(NSIndexPath(forRow: 0, inSection: 0), atScrollPosition: .Top, animated: false)
这会导致tableView出现在屏幕上较晚,但我认为在tableView出现后它可以接受而不是冻结UI。当你在开始时调用API时会更好,因为它感觉网络有点延迟,而不是UI延迟。
在此之后,tableView跳转到单元格的准确位置。
是的,我也不喜欢这个解决方案:|
编辑:
我这样做的唯一原因是通过调用cellForRowAtIndexPath:
来计算实际的行高,但是我发现在通过委托方法estimatedHeightForRowAtIndexPath:
为每一行提供正确的estimatedHeight时,而不是给{UITableView.estimatedRowHeight
提供静态值1}}解决了这个问题。
我最终做的是将willDisplayCell:forRowAtIndexPath:
行的高度缓存到磁盘,并在estimatedHeightForRowAtIndexPath:
上使用该值。
通过这样做,所有行的estimatedHeightForRowAtIndexPath:
在开始时被调用,而scrollToRowAtIndexPath
效果很好。
答案 2 :(得分:1)
这不是最漂亮的解决方案,但我使用了解决这个问题的解决方法。始终将estimatedRowHeight更新为最高的计算单元格,然后使用以下内容:
通过调用scrollToRowAtIndexPath来索引路径零来完成。
[self.tableView setContentOffset:CGPointZero animated:YES];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]
atScrollPosition:UITableViewScrollPositionTop
animated:YES];
});
结果tableView应该非常顺利地滚动到顶部。
答案 3 :(得分:1)
我的解决方案是设置estimatedRowHeight to 0
答案 4 :(得分:1)
这解决了我的问题
let oldContentSize = tableView.contentSize
tableView.scrollToRow(at: indexPath, at: .top, animated: true)
// Called again when tableView contentSize change
if !tableView.contentSize.equalTo(oldContentSize) {
tableView.scrollToRow(at: indexPath, at: .top, animated: true)
}
答案 5 :(得分:0)
仍然没有可靠的解决方案,但对我来说,执行一个没有动画的滚动是可以接受的,因为它滚动到具有正确偏移的预期单元格,尽管http://www.openradar.me/20829131中提到了什么。 / p>
self.tableView.scrollToRowAtIndexPath(indexPath, atScrollPosition:.Top, animated: false)
答案 6 :(得分:0)
在视图由系统布局后似乎可以工作。我正在VC的viewDidAppear中调用scrollToRowAtIndexPath并获得正确的结果。当然,这不是很漂亮,因为它在视图已经可见时滚动...
答案 7 :(得分:0)
尝试在返回单元格之前在-cellForRowAtIndexPath:中添加此代码
[cell layoutIfNeeded]
答案 8 :(得分:0)
我的错误是因为“ atScrollPosition”设置为UITableViewScrollPositionNone
-将其更改为UITableViewScrollPositionMiddle
,它应该可以正常工作