简体   繁体   中英

UITableView not scrolling all the way to top after resorting dynamic size cells and setting content offset to top

I have a tableview with dynamically sized cells, and a button that toggles the sort order of these cells. I'd like to scroll to the top every time the sort order is toggled, but when I set the content offset to the top, it seems to only scroll ~90% of the way there.

The offsetting code is simple enough and has served me well on different projects, so I seriously doubt the problem is here:

- (void) scrollToTop
 {
    CGPoint offset = CGPointMake(0, -self.tableView.contentInset.top);
    [self.tableView setContentOffset:offset animated:YES];
}
    [self.tableView reloadData]; // Lets update with whatever info we have
    [self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] atScrollPosition:UITableViewScrollPositionTop animated:NO];

reloading and then scrolling resolved for me.

Didn't think I would find the answer so soon.

I was using UITableView's tableView:estimatedHeightForRowAtIndexPath: to return my minimum cell height, and it seems that the tableview uses this inside reloadData to create an idea of how big the content is before actually dequeuing the cells and caching their height. Being halfway down the content and reloading the data causes the tableview to think the distance to the top is the (number of cells offscreen above the current visible * the minimum height from estimatedHeightForRow ), causing the tableview to only offset itself as if all cells were the minimum height. My solution was just to avoid using the estimated height, since my tableview isn't excessively long anyway. If you do have a large tableview (approaching 1000+ rows) that actually needs to use the estimated values for performance reasons, you might want to find a way to make the estimated values as close to the runtime values as possible, or look into more detailed solutions.

tl;dr - Remove tableView:estimatedHeightForRowAtIndexPath: and just allow the tableView to size itself from heightForRowAtIndexPath

What about something like this instead?

NSIndexPath *start = = [NSIndexPath indexPathForRow:0 inSection:0];
[self.tableView scrollToRowAtIndexPath:start atScrollPosition:UITableViewScrollPositionTop animated:YES];

None of these worked for me. The solution was to call layoutIfNeeded() before setting the content offset:

tableView.reloadData();
tableView.layoutIfNeeded();
tableView.setContentOffset(CGPoint.Empty, animated: true);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM