swift - TableView w。重新加载新数据时动态高度滚动

标签 swift uitableview

总结 在顶部插入新单元格时,我的具有动态单元格高度的 UITableView 会随机滚动。

详细说明 作为 UITableViewController 的一部分,为了避免在我触发 reloadData() 和滚动时滚动不准确,我有以下基于此堆栈溢出的工作实现 answer :

var cellHeightsDictionary: [IndexPath: CGFloat] = [:]   

override func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {  
      cellHeightsDictionary[indexPath] = cell.frame.size.height  
}  

override func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {  
  if let height =  cellHeightsDictionary[indexPath] {  
      return height  
  }  
  return UITableView.automaticDimension  
}  

除了在数据源的顶部添加新数据并触发 reloadData() 之外,这工作得很好。这样做时,我还没有找到一个合适的实现来防止表格随机滚动……这就是我要解决的问题。

我尝试过的

  1. 我尝试使用更新前后的 contentSize 的差异,然后更新滚动位置。不幸的是,根据我在 Apple 文档中阅读的内容,似乎在使用动态单元格时,contentSize 不能用于此目的,并且对我不起作用。不过作为引用,这里是我的一个实现。

    UIView.performWithoutAnimation { //检测单元格相对于导航栏的确切位置 让 navBar = navigationController?.navigationBar 让 cellRectInTable = tableView.rectForRow(位于:IndexPath(行:topArticle + countOfAddedItems,部分:0)) 让 positionVsNavBar = tableView.convert(cellRectInTable.origin, to: navBar) 让 positionVsTop = tableView.convert(cellRectInTable.origin, to: tableView.superview) 让 offsetOfCell = positionVsTop.y - positionVsNavBar.y tableView.reloadData() tableView.scrollToRow(位于:IndexPath(行:topArticle + countOfAddedItems,部分:0),位于:.top,动画:false) tableView.contentOffset.y = tableView.contentOffset.y + offsetOfCell }

  2. 我尝试在添加之前设置 tableView.estimatedRowHeight = 0、tableView.estimatedSectionHeaderHeight = 0 和 tableView.estimatedSectionFooterHeight = 0,但似乎没有任何影响。

  3. 似乎最有效的方法是当我从 cellHeightsDictionary 获取单元格的高度并根据添加的数量对它们求和时。这有时会完美无缺地工作,但有时却不会。此外,当添加大量行时,它可能会崩溃,因为它没有在 cellHeightsDictionary 中找到值。我尝试了多种变体,但没有成功。同样重要的是,我不确定为什么这给了我最好的结果,所以我可能会遗漏一些明显的东西。我感觉最后一个实现中的某个地方就是答案,但我一直无法找到它。

    var 迭代器计数器 = 0
    var heightCum = CGFloat(整数文字: 0)
    而 iteratorCounter < countOfAddedItems {
    heightCum = heightCum + cellHeightsDictionary[IndexPath(row: iteratorCounter, section: 0)]!
    迭代器计数器 = 迭代器计数器 + 1
    }

    UIView.performWithoutAnimation {  
       tableView.reloadData()  
       tableView.layoutIfNeeded()  
       tableView.contentOffset.y = tableView.contentOffset.y + heightCum   
    }
    

我已经尝试了我能想到的一切,并在我想到的所有地方进行了搜索,但没有成功。任何帮助表示赞赏

感谢一百万!

最佳答案

作为最后的手段,您可以将 TableView 嵌入到新的 ScrollView 中并关闭 TableView 的滚动。您可以完全控制滚动行为(尽管都是以编程方式)。

在这种情况下,我们必须添加一个布局约束对应于表格 View 的高度,以及这个约束的导出。

如果我们的单元格 View 有适当的布局,我们可以使用 systemLayoutSizeFittingSize 方法计算准确的单元格高度。如果单元格有多个标签(例如动态内容),请尝试使用固定宽度进行计算(在单元格中添加显式宽度限制)。

有了这个,我们可以重新加载 TableView ,如下所示:
1)向数据源插入数据
2) 重新计算内容高度
3)修改高度约束常量
4) 调用layoutIfNeeded
5) 重新加载 TableView
6) 适当移动 ScrollView 内容偏移=> setContentOffset(_ contentOffset: CGPoint, animated: Bool)

关于swift - TableView w。重新加载新数据时动态高度滚动,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53830667/

相关文章:

iphone - TableView,如何更改单元格默认蓝色

objective-c - Obj-C - 导入(Swift 编译器识别?)

iphone - UITableview 部分标题不显示文本

ios - 如何从键盘打印格式化文本

ios - 如何更改 UIScrollView 指示器颜色?

ios - 在 IOS 的 ImageView 中从 API 多次加载图像

ios - 如何更改特定 TableViewCell 中的按钮颜色

ios - 从UITableView删除多行

ios - CAShapeLayer 左上角缺少像素

ios - 无法解决 "Could not build module "UIKit”