UITableView: scrolling to the bottom with user / variable cell heights is inaccurate on initial scrolling

Edit: https://streamable.com/rfym will show it in action. The first time I click Scroll To Bottom, it does not reach the end. Then I manually get to the end and quickly scroll back all the way. When I click Scroll To Bottom again, it works correctly because it uses cachedHeights.

So, I saw a lot of answers for this, but none of them seem to work for me, and I'm sure they don't work for many others either:

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

Boom, instantly, my tableView disappears.

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

Inaccurate. He does not go to the bottom. Sometimes it howls!

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

Again, like the previous one, this is inaccurate.

I know why this is inaccurate. I need a solution for this ...

:

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 return 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)
}
+4
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
    }
}
0

Source: https://habr.com/ru/post/1608699/


All Articles