The problem: When I'm at the bottom of the UITableView
(and only when at the bottom) and tableView.beginUpdates()
/tableView.endUpdates()
is called, the UITableView
jumps up a little bit. I don't want it to do this.
Set Up: I have a UITableView
with UITableViewCells
that will all be different sizes, and I'm using UITableViewAutomaticDimension
to size the cells.
Example: When I'm at the bottom of the UITableView
and I select a cell, which subsequently calls tableView.beginUpdates()
/tableView.endUpdates()
, the UITableView
scrolls/jumps up just a bit.
Has anyone found a way to make it so there's no jumpiness after calling tableView.beginUpdates()
/tableView.endUpdates()
while at the end of the UITableView
?
For the time being I'm calculating all my UITableViewCells
manually, I'd rather not do this though because I'd like to take advantage of UITableViewAutomaticDimension
.
Code:
Here's some code to display what goes on between tableView.beginUpdates()
/tableView.endUpdates()
:
tableView.beginUpdates() cell!.setNeedsUpdateConstraints() cell!.updateConstraintsIfNeeded() cell!.setNeedsLayout() cell!.layoutIfNeeded() tableView.endUpdates()
My viewWillAppear:
public override func viewWillAppear(animated: Bool) { super.viewWillAppear(animated) self.tableView.estimatedRowHeight = 150.0 self.tableView.rowHeight = UITableViewAutomaticDimension self.tableView.reloadData() //Bug in 8.0+ forces us to call three extra methods to get dynamic cell heights to work correctly... self.tableView.setNeedsLayout() self.tableView.layoutIfNeeded() self.tableView.reloadData() }
My heightForRow:
public override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat { return UITableViewAutomaticDimension }
Update: Removing cell!.setNeedsUpdateConstraints()
, cell!.updateConstraintsIfNeeded()
, cell!.setNeedsLayout()
, and cell!.layoutIfNeeded(
) from tableView.beginUpdates()
/tableView.endUpdates()
appears to stop the jumping, but then my cells do not resize...
Edit: This only occurs when at the bottom of the UITableView
.
Actually I found a nice method to fix this.. It drove me crazy but look:
So you
And soo the table jumps..
As others have said before, it is because updating the tableView makes the tableView Scroll
The solution?
Let's assume your code looks like this:
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { let cell = tableView.cellForRow(at: indexPath) cell.heightConstraint = 100 UIView.animate(withDuration: 0.15, animations: { self.view.layoutIfNeeded() self.tableView.beginUpdates() self.tableView.endUpdates() }, completion: nil) }
Then to fix the jumping issue you have to save the current tableView scroll position until the tableView.endUpdates() being called.
Like this:
var currentScrollPos : CGFloat? override func scrollViewDidScroll(_ scrollView: UIScrollView) { // Force the tableView to stay at scroll position until animation completes if (currentScrollPos != nil){ tableView.setContentOffset(CGPoint(x: 0, y: currentScrollPos!), animated: false) } } override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { let cell = tableView.cellForRow(at: indexPath) cell.heightConstraint = 100 UIView.animate(withDuration: 0.15, animations: { self.currentScrollPos = self.tableView.contentOffset.y self.view.layoutIfNeeded() self.tableView.beginUpdates() self.tableView.endUpdates() self.currentScrollPos = nil }, completion: nil) }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With