【问题标题】:UITableView: Scrolling to the bottom with custom/variable cell heights is inaccurate on the initial scrollUITableView:使用自定义/可变单元格高度滚动到底部在初始滚动时不准确
【发布时间】:2015-12-21 00:57:20
【问题描述】:

编辑:https://streamable.com/rfym 将在行动中展示它。我第一次按滚动到底部时,它并没有一直到底部。然后我手动一直到底部并快速向上滚动。一旦我再次按下滚动到底部,它就会正常工作,因为它正在使用缓存高度。

所以,我已经看到了很多答案,但似乎没有一个对我有用,而且我很确定这些对许多其他人也不起作用:

tableView.setContentOffset(CGPointMake(0, CGFloat.max), animated: true):

轰,瞬间,我的 tableView 消失了。

tableView.setContentOffset(CGPointMake(0, self.tableView.contentSize.height - self.tableView.frame.size.height), animated: true):

不准确。它不会一直到底部。有时,它会超调!

tableView.scrollToRowAtIndexPath(NSIndexPath(forRow: self.replies.count - 1, inSection: 0), atScrollPosition: .Bottom, animated: true)

再一次,和前一个一样,这是不准确的。

我知道为什么这是不准确的。我需要的是一个解决方案...

下面是一段代码:

class RepliesTableViewController: UITableViewController {

    var cachedHeights = [Int: CGFloat]()

    override func viewDidLoad() {
        super.viewDidLoad()

        tableView.rowHeight = UITableViewAutomaticDimension
    }

    override func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
        self.cachedHeights[indexPath.row] = cell.frame.size.height
    }

    override func tableView(tableView: UITableView, estimatedHeightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
        if let height = cachedHeights[indexPath.row] {
            return height
        } else {
            return 113
        }
    }
}

请记住,只有初始滚动到底部不会一直滚动。如果我用手指一直滚动到底部,然后向上滚动到顶部并触发滚动到底部,那就完美了。

原因很简单:我会在每个单元格上触发tableView.willDisplayCell,这意味着所有高度都已缓存。这意味着tableView.estimatedHeightForRowAtIndexPath 在初始滚动后可以完美运行。

但是,如果我从不滚动到底部以缓存所有高度并且我尝试以编程方式滚动到底部,它就不会到达那里。为什么?因为我有 tableView.estimatedHeightForRowAtIndexPath 返回 113。

有些人可能会争辩说我需要一个更准确的估计,但我拒绝接受这种想法。我的细胞可以小到 50 个,大到 5000 个。没有准确的估计

如何缓解这种情况?

也许我需要在不同的时间缓存我的所有身高?那是几点?我不想自己做任何计算。 tableView.willDisplayCell 的美妙之处在于我可以缓存 cell.frame.size.height 而不是自己进行繁琐的计算。

编辑 2:我有一个有趣的解决方案……它非常笨拙……而且不可接受……但从技术上讲它是有效的。为娱乐而附加。

func scrollToBottom() {
    self.tableView.scrollToRowAtIndexPath(NSIndexPath(forRow: self.replies.count - 1, inSection: 0), atScrollPosition: .Bottom, animated: true)
}

override func scrollViewDidEndScrollingAnimation(scrollView: UIScrollView) {
    if !atBottom {
        self.tableView.setContentOffset(CGPointMake(0, tableView.contentOffset.y + 200), animated: true)
    }
}

override func scrollViewDidScroll(scrollView: UIScrollView) {
    atBottom = scrollView.contentOffset.y >= (scrollView.contentSize.height - scrollView.frame.size.height)
}

【问题讨论】:

  • 我可以看到它发生的 GIF 吗?只需访问 makeagif.com。
  • @JohnDoe 检查我在顶部或此处包含的可流式链接:streamable.com/rfym 请注意,我第一次按滚动到底部时.. 它并没有一直走下去。然后,我手动到底部。当我往回走,再次按下按钮时,它成功地一直到底部。
  • 您是否尝试在视图出现时刷新所有内容?
  • 我从服务器异步加载我的数据,所以只要它进来就会重新加载。
  • 好的,你应该去检查一下 eddwinpaz 是否回答了这个问题。看起来他明白了。

标签: ios swift uitableview uiviewcontroller uitableviewautomaticdimension


【解决方案1】:
self.tableView.rowHeight = UITableViewAutomaticDimension;
self.tableView.estimatedRowHeight = 113.0; // set to whatever your "average" cell height is

这样您的 tableCell 将重新定位而不会出现您提到的不准确

更新:(删除此功能)

 override func tableView(tableView: UITableView, estimatedHeightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
    if let height = cachedHeights[indexPath.row] {
        return height
    } else {
        return 113
    }
}

【讨论】:

  • 只是为那些不在聊天中的人迭代这里,但这不起作用。 :(
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-22
  • 1970-01-01
  • 2012-10-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多