2
votes

In ios, where's the best place in a view controller to move your custom subviews around to handle rotations? (of course this is only for those where the autoresizingflags don't help).

Here's the following places i've tried, and the issues each has:

  • willAnimateRotationToInterfaceOrientation:duration

This works, and any subview frame changes you make are animated nicely as the device is rotated landscape<->portrait. However, if you're in a tab controller, this doesn't get called when another VC is visible. And so if you rotate, and switch back to this tab, it'll have the wrong layout.

  • viewWillAppear

Doesn't really help, because this gets called before the rotation takes effect, so when accessing self.view.frame you get the pre-rotation sizing, so you can't know whether we're going for landscape or portrait

  • viewDidAppear

This is better than viewWillAppear, however because it gets called after the view goes on screen, you see a flash of content in the wrong layout before it flicks across.

I just want to know where the proper place is to put my code that lays out my view controller's subviews nicely to handle both layouts, animated nicely. THanks all

3

3 Answers

4
votes

I usually have my own layoutViewsForOrientation:(UIInterfaceOrientation) method which I call both from willAnimateRotationToInterfaceOrientation:duration (to get the nice animations you mention), and from my viewWillAppear: (with self.interfaceOrientation) to set up my view before it appears.

So the answer is that the proper place to layout your view is whenever something changes and you're not sure that it's in the proper orientation, and you can use a layout function to keep your code clean.

2
votes

The problem here, from my experience, is that if the UIViewController is not visible, it won't rotate. You can have 3 tabs each one with a distinct UIViewController (A,B and C). If you are in A and you rotate, B and C won't. I resolved this, by having a UIViewController (Lets call it D) to hold the UITabBarController, then in this UIViewController I have a reference to each UIViewController (A,B and C) so i just call the willAnimateRotationToInterfaceOrientation:duration method for each UIViewController when D rotates. Works very well for me. :)

0
votes

The best i've come up with personally is to grab every event, seems to work, but its worrying me that there should be a better way to do this, and that i'm doing something wrong.

- (void)doMyResizing {
    self.somesubview.frame = ...
}
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
    [super willAnimateRotationToInterfaceOrientation:toInterfaceOrientation duration:duration];
    [self doMyResizing];
}
- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
    [self doMyResizing]; // This is for the case when the person uses this tab in portrait, changes to another tab, rotates to landscape, and switches back to this tab
}
- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    [self doMyResizing]; // This is for the case when the person uses this tab in portrait, changes to another tab, rotates to landscape, and switches back to this tab
}