简体   繁体   中英

Swift 3 | TableView ScrollToTop on reloadData with dynamic cell size

I have a TableView with dynamic cell size :

tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 20

I have cells with texts inside and, of course, the text Height can change in function of its content.

Sometimes I have only one line, sometimes I have more, it means sometimes my cells does 20 height, sometimes more.

I have an issue when I try to reload my tableview datas and scroll to the top.

This is what I do :

myTableViewDatas = newDatas
tableView.setContentOffset(CGPoint.zero, animated: false)
tableView.reloadData()

It is hard to show you this case but It doesn't scroll to Y = 0 , it scrolls to Y = 100 or something like that. Because my cell size changes in function of the content to display.

If I remove dynamic size and do :

func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    return 20
}

And still scroll to the top with :

myTableViewDatas = newDatas
tableView.setContentOffset(CGPoint.zero, animated: false)
tableView.reloadData()

==> This is working, I scroll to Y = 0

I think I tried anything :

  • scrollToRow

  • scrollRectToVisible

  • scrollsToTop

I still have the issue. The only way this is working is if I delay the reloadData :

myTableViewDatas = newDatas
tableView.setContentOffset(CGPoint.zero, animated: false)
DispatchQueue.main.asyncAfter(deadline: .now() + 0.01) {
    tableView.reloadData()
}

This is working but It creates a "glitch" => It displays new datas then automatically scroll to top, this is disturbing for the user.

The other solution is to use "reloadSections" :

myTableViewDatas = newDatas
tableView.setContentOffset(CGPoint.zero, animated: false)
tableView.reloadSections(IndexSet(integer: 0), with: .none) // I have only one section

It works too but it is also creating a "glitch", this is like TableView is reloaded with an animation (even if I set .none) where cells displayed are reduced / enlarged in function of new datas.

I really can't find a "proper" solution to do this, does anyone as already encountered this issue ? TY

Well, sometimes you search complicated solutions and It is simple in fact. I did : - reload first - scrollToIndexPath 0 second -> It works

myTableViewDatas = newDatas
tableView.reloadData()
tableView.scrollToRow(at: IndexPath(row: 0, section: 0), at: .top, animated: false)

I also have the same issue. [UITableView reloadData] doesn't work how we expected. It doesn't layout tableView from the cleanslate.

Reloads everything from scratch. Redisplays visible rows. Note that this will cause any existing drop placeholder rows to be removed.

It says redisplays visible rows. So this is what I did.

data = nil;  // clear data.

[tableView reloadData];  // reloadd tableView so make it empty.

[tableView setNeedsLayout];  // layout tableView.
[tableView layoutIfNeeded];

data = the data;  // set the data you want to display.

[tableView reloadData];   // reload tableView

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