Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

bug in UITableView layout after orientation change

I have an auto-layout (constraint) based application and noticed that there is a problem with a tableview after an orientation change. The repro steps are as follows (I have a very basic repro app - with a tableview and an add button that adds a new item).

  1. Rotate your application to Landscape mode so the tableview is now landscape.
  2. Add an item to the tableview see 1 below
  3. Rotate back to Portrait, the tableview will now float on horizontal pan (as though the scroll viewer content size is landscape), see [2]

1 Code to add

- (IBAction)onAdd:(id)sender {
    count ++;
    [self.tableView insertRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:count-1 inSection:0]] withRowAnimation:UITableViewRowAnimationBottom];
}

[2] Floating table view

enter image description here

Any ideas on how to work around this problem? Also, how can I tell if this is known issue or something I should report to Apple?

like image 813
ConfusedNoob Avatar asked Jan 13 '13 19:01

ConfusedNoob


2 Answers

I think this is a bug; if you convert the project away from auto layout and set appropriate resizing masks, everything works just fine. You should file a bug, particularly since you have a simple sample project that reproduces it nicely.

What is happening in your case is as you suspected - the scroll view's content view remains at the landscape width, even though the view itself has resized to portrait, so you suddenly get the ability to horizontally drag.

Luckily there are fairly simple workarounds. I experimented with various combinations of setNeedsLayout or setNeedsUpdateConstraints without success, but you can implement one of these two solutions:

-(void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
    [self.tableView beginUpdates];
    [self.tableView endUpdates];
}

Or,

-(void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
    CGSize contentSize = self.tableView.contentSize;
    contentSize.width = self.tableView.bounds.size.width;
    self.tableView.contentSize = contentSize;
}
like image 79
jrturton Avatar answered Nov 17 '22 16:11

jrturton


I have found that the answers above work most of the time but not all of the time. The most robust solution is to subclass UITableView and set the contentSize within layoutSubviews:

- (void)layoutSubviews
{
    [super layoutSubviews];

    CGSize contentSize = self.contentSize;
    contentSize.width  = self.bounds.size.width;
    self.contentSize   = contentSize;
}
like image 25
phatmann Avatar answered Nov 17 '22 16:11

phatmann