如何让 uitableview 知道在哪里滚动未创建的视图

Posted

技术标签:

【中文标题】如何让 uitableview 知道在哪里滚动未创建的视图【英文标题】:how to make a uitableview know about where to scroll for uncreated views yet 【发布时间】:2015-06-27 20:51:31 【问题描述】:

我有一个 UITableView,其中包含多达 600 个项目。它们分为标题和项目(例如 30 个标题,每个标题有 15-20 个项目)。它是一个目录,必须模仿印刷的目录。

还有一个导航弹出视图,仅显示用户可以覆盖到主表视图的标题。它是这样表示的:

header
 \subheader
header2
\subheader
  \subheader

而我们的导航代码是这样的:

  func tapOnMenuHeaderView(recognizer: UITapGestureRecognizer)
  
    self.hideModalNavigation()
    self.mainTV.reloadData()
    self.mainTV.scrollToRowAtIndexPath(NSIndexPath(forRow: self.menuHeaderPositions[recognizer.view!.tag]!, inSection: 0), atScrollPosition: UITableViewScrollPosition.Top, animated: true)
  

但是,它没有多次去正确的地方。它似乎总是很短,并且越往下越不准确。这是对 scrollRowAtIndexPath 的限制吗?有没有办法可以强制完全重新加载?我可以让它工作的唯一方法是使用 tableview 删除并将所有内容作为 UIViews 并在滚动视图中增加它。我将如何使我们的叠加导航滚动到正确的位置?

使用 heightForRowAtIndexPath 编辑 #1

因此,通过创建和填充我们的一个自定义单元格,它确实设置了正确的 cellHeight,即使在使用 scrollToRowAtIndexPath 时也是如此。重要的一点是自动滚动不会调用 cellForRowAtIndexPath。但是,在初始 reloadData 上调用 heightForRowAtIndexPath 允许正确计算此值。代码:

  func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat 
    println("within heightForRowAtIndexPath \(indexPath.row)")
    let item = self.tableItems[indexPath.row];
    if let menuHeader = item as? EKMenuHeader 
      // cellHeight is a property on the models that is defaulted to 0.0
      if (menuHeader.cellHeight == 0.0)
        let tableViewCell = EKMenuHeaderCell()
        tableViewCell.updateCell(menuHeader)
      
      return CGFloat(menuHeader.cellHeight)
     else if let menuItem = item as? EKMenuItem 
      if (menuItem.cellHeight == 0.0)
        let tableViewCell = EKMenuItemCell()
        tableViewCell.updateCell(menuItem)
      
      return CGFloat(menuItem.cellHeight) // not the default value
    else
      return 30.0  // some that are neither
    
  

我已经对此进行了 10 次不同的测试,并且对所有 350 个项目都调用了 heightForRowAtIndexPath。

【问题讨论】:

滚动基于估计的行高。估计越准确,表格越能滚动到单元格或节标题的正确偏移量。 它应该滚动到确切的索引位置。如果我滚动到喜欢的位置 500,然后滚动到顶部,它能够弄清楚,所以这意味着它似乎只是不知道这个位置的位置。看来您应该能够强制它计算预期的位置。 它不知道确切的位置,因为它没有计算出当前 indexPath 和新 indexPath 之间每个单元格的确切高度。我向您保证,它会滚动到 indexPath 的估计偏移量。它无法确定确切的位置,除非它已逐行滚动并确定了新 indexPath 之前的每个确切高度。使用更准确的估计,否则错误会更明显,正如您的问题所提到的,它必须进一步估计。 嗯...我觉得有一种解决方法可以使这项工作。您的意思是该方法不符合说明 Scrolls through the table view until a row identified by index path is at a particular location on the screen. ;不会是第一次,但有点令人不安 在UITableView scrollToRowAtIndexPath scrolls to wrong offset with estimatedRowHeight on ios 7 的回答中阅读笑脸的 cmets。该方法没有做你认为它正在做的事情。它不会为每一行填充数据。如果您使用estimatedRowHeightestimatedHeightForRowAtIndexPath:UITableViewAutomaticDimension,则会出现不准确,随着您滚动的进一步增加,除非您的估计与实际高度相符。 【参考方案1】:

scrollToRowAtIndexPath: 使用estimatedRowHeight(或estimatedHeightForRowAtIndexPath:)来确定您滚动到的行的近似偏移量。然后 tableView 将显示该行以及任何其他可能可见的周围行。

它不会逐行滚动,在滚动时计算单元格的确切行高,因为那样效率不高。

这就是为什么,当你滚动得越远,当估计不是很准确时,位置就会越远。

除非您让 tableView 计算表格中每一行的准确高度,否则它将无法滚动到该行实际所在的精确位置。

由于您尝试在单独的视图中“同步”表格行的位置以及重叠的标题,您要么必须:

完全放弃使用任何估计,并诉诸计算表格中每一行的准确高度(通过删除任何自动或估计的大小,并实施heightForRowAtIndexPath:)。

等到表格滚动后,确定可见偏移量,然后调整叠加层以使其与表格的行的大致位置对齐

您还可以将重叠的数据移动到 tableView 标题中,因此不再需要保持两个独立视图同步。

【讨论】:

感谢 Petah - 几个复杂的决定。我确实计算了您当前正在滚动的表格视图单元格的确切高度,但显然只有在表格视图已滚动到这一点时才会发生这种情况。我认为它效率不高,但是当实现为 1000 个 UITableView(而不是具有 1000 条记录的 UITableView)时,性能很好。 考虑到这一点,由于导航片将在初始表填充后被调用,是否可以执行滚动到表底部的操作,以便获取 scrollToRowAtIndexPath 的所有信息人口稠密?理想情况下,关闭屏幕以便用户界面中没有任何东西可以看到?我正在考虑将标题作为部分进行,但我不确定这是否会有所帮助。 如果您在顶部,并且您 scrollToRowAtIndexPath: 到最后一行,它不会计算每个单元格滚动时的高度。您可以通过记录并查看仅计算最后一行和附近单元格的高度来验证这一点。它使用estimatedRowHeight 来估计不可见的单元格的高度。这就是估计的目的,以避免必须确定每一行的高度,但它确实会引入这种“错误”,即不准确的估计会导致表格的感知(估计)大小与其真实大小之间存在差异。 以编程方式滚动到底部不会填充所有行的确切高度信息。手动滚动到底部会。您不能以编程方式滚动到底部并期望它确定每个单元格的高度,但您可以停止使用估计值,这将强制表格计算每一行的高度,甚至在以编程方式滚动表格之前。 (estimatedRowHeight 是在 iOS 7 中添加的。在优化之前,tableView 实际上必须计算所有单元格高度才能知道其内容大小。) 感谢评论,我在编辑#1 中用看起来像 sol'n 的东西更新了这个问题。我认为这就是你在第一个 sol'n 中所要达到的目的

以上是关于如何让 uitableview 知道在哪里滚动未创建的视图的主要内容,如果未能解决你的问题,请参考以下文章

如何让 UITableView 在动态高度单元格中滚动到底部?

UITableView 在 reloadData 后自动向下滚动

如何让 UI 组件与我的 UITableView 一起滚动

UITableView中的多个UICollectionView在滚动中交织在一起

即使在用户可见之前,如何将 UITableView 滚动到所需的行?

防止表视图被重用(MVVM)