我的tableView
中有动态单元格高度tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 100
我想和whatsapp app(分页)做同样的事情,我想加载25乘25行,所以当用户在顶部滚动时,我想加载新数据但我想保持相同的滚动位置,这里是我的意思确实
func scrollViewDidScroll(_ scrollView: UIScrollView) {
if isMore && scrollView.contentOffset.y == 0 {
loadMore() // function that add new data in my model
self.tableView.reloadData()
}
}
我遇到的问题是在我到达我的tableview顶部后调用reloadData但是tableView滚动到UP
我测试了其他类似的解决方案:
var cellHeights: [IndexPath : CGFloat] = [:]
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
cellHeights[indexPath] = cell.frame.size.height
}
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
guard let height = cellHeights[indexPath] else { return 70.0 }
return height
}
但仍然无法正常工作
答案 0 :(得分:0)
如果要重新加载表以添加更多数据,那么在重新加载调用下面的函数后保留滚动位置。
tableview.scrollToRow(at: indexPath, at: .middle, animated: true)
这里indexPath是重载前最后一个单元格的indexPath。
答案 1 :(得分:0)
在tableView:cellForRowAt
中,当您检测到indexPath
接近最后一个元素时(indexPath.row
接近yourArray.count
时),请查询更多项目。如果有它们,请将它们添加到数据源(数组或其他任何内容,表中包含所有对象)并重新加载表视图。表视图应显示新项目,用户可以继续滚动而不做任何特殊操作。
您不应该等到最后一个单元格调用tableView:cellForRowAt
,因为如果您需要调用服务器来获取更多项目,则用户必须等待。 Whatsapp的滚动很快,因为他们在你滚动到最后一个元素之前很好地下载了这些项目(前一段时间它确实停止了,但现在他们可能更早地获取新项目)。
请记住,25个项目可能太少,网络速度慢,用户可能会滚动浏览您要显示的更多项目之前的项目,并且必须等待,这不是一个好的用户体验。模拟慢速网络连接,看看当您的应用与服务器联系时,25个项目是否足以滚动(取决于网络速度,请求和响应大小,服务器响应请求的速度等)。
答案 2 :(得分:0)
我在消息传递应用程序中遇到了同样的问题。这就是我解决它的方法:
为数据源阵列中的每个消息分配了唯一的messageId
。
在cellForRow:
中,我保存了名为messageId
的变量中第一行的messageIdFirst
。
if(indexPath.row == 0){
messageIdFirst = message.id!
}
在loadMore()
方法中,我检查当前 indexpath 行在当前更新的数据源数组中是否具有相同的 messageId 。
if(message.id == messageIdFirst){
previousTopIndexPath = i
}
,其中i是数据源数组中具有相同messageId.
现在,我滚动到previousTopIndexPath
,就像这样:
tableview.scrollToRow(at: previousTopIndexPath, at: .middle, animated: true)
注1 :由于这在UITableView
中效率不高,我最终使用UICollectionView
使用相同的解决方案。
注2:虽然这确实很顺利,但我知道必须有更清洁的方法来实现这一目标。