Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I fix or workaround this tableView textField autolayout glitch?

I think the root cause is that the estimatedRowHeight is used to make assumptions about the underlying UIScrollView.contentOffset, but this will always be wrong by definition as it is a estimate. The real row heights are completely different depending on the cell content and device orientation.

Even if I implement estimatedHeightForRowAtIndexPath to provide closer estimates the glitches are still there.

So when you start at the top and scroll down all is well because the TableView learns the actual cell heights as it goes keeping the contentOffset in sync with the cell positions. But as soon as you rotate all the real cell heights change so the UITableView is now way out of sync, it doesn't know where to scroll to.

But there are even stranger things happening too, sometimes the UITextField cell will end up on top of another cell, and remain stuck there...

Anyway I have boiled it all down to a simple example.

https://github.com/trapper-/autolayout-glitch

  • Test with iPhone and if using simulator then enable the software keyboard.
  • You will see many visual glitches just playing around scrolling, selecting fields and rotating.
  • For a simple repeatable example.
  • Scroll down to the bottom.
  • Select one of the last couple of UITextField's, so that the UITableView will need to scroll to ensure the field will be visible.
  • Rotate the device.
like image 920
trapper Avatar asked Dec 08 '16 01:12

trapper


1 Answers

I toyed with your code for a few minutes, because I struggled through similar issues. I was hopeful I could help, but I didn't get it fully fixed.

What I can offer is that I did make some progress.

When the device rotates, you should implement the UIViewcontroller methods that tell you it will happen, and did happen. When it will happen, cache off the visible rows. Then after it did, reload the table and scroll to those visible rows.

It looks like this:

- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
    // Save the visible row position
    self.visibleRows = [self.tableView indexPathsForVisibleRows];
}

-(void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
    [self.tableView reloadData];
    // Scroll to the saved position prior to screen rotate
    [self.tableView scrollToRowAtIndexPath:[self.visibleRows objectAtIndex:0] atScrollPosition:UITableViewScrollPositionBottom animated:NO];
}

visibleRows is an array @property on your ViewController.

This made it go to the rightish place ( I suspect that if you actually stored off the individual cell that the user was manipulating, this would get you 100% to the right cell every time.

What this did not do, is that there were still the dancing UITextFields being laid out incorrectly (on occasion) with several device rotations.

Again, not a solution - but I wanted to share what I saw so hopefully this helps you find the solution.

Good Luck!

like image 171
Brian Trzupek Avatar answered Nov 17 '22 13:11

Brian Trzupek