I have a custom view controller that can contain two child view controllers. The view of one of the controllers is made visible when the device is in portrait orientation. The view of the other controller is made visible when the device is in landscape orientation. When the landscape orientation view is made visible, however, the status bar is retracted to make more room for the particular view. The status bar is unhid after the device is turned back into portrait mode. This is custom view controller is displayed within a UINavigationController
.
My problem is that my subviews are not adjusting properly when the status bar's visibility changes. There ends up being a big gap and/or overlap when you turn the device in the different orientations as pictured below:
As you can see, it is initially fine (in portrait), but when the device is turned, there is a white gap where the status bar was. When the device is turned back to portrait, the UINavigationController
's navigation bar is brought up and overlapped by the status bar and a gap between navigation bar and the view below it appears. If you are very quick to rotate 180 degrees from one landscape orientation to the opposite landscape orientation, the gap disappears and looks good.
The method below belongs to the custom view controller and is called in willAnimateRotationToInterfaceOrientation:duration:
(obviously to handle rotation events) and viewDidAppear:
(to handle when the view pushed in from the previous view controller in the navigation stack).
- (void)cueAnimationToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation fromViewDidAppear:(BOOL) fromViewDidAppear
{
// Fading animation during orientation flip.
// Make sure its not already animating before trying.
BOOL barHidden = [UIApplication sharedApplication].statusBarHidden;
if (!isAnimating) {
BOOL alreadyGoodGrid = (UIInterfaceOrientationIsLandscape(interfaceOrientation) && curView == self.gridViewController.view);
BOOL alreadyGoodTable = (UIInterfaceOrientationIsPortrait(interfaceOrientation) && curView == self.tableViewController.view);
if ((alreadyGoodGrid && barHidden) ||
(alreadyGoodTable && !barHidden)) {
// If views are the way they should be for this orientation. Don't do
// anything.
return;
}
isAnimating = YES;
UIView *nextView;
// Get starting orientation. This will determine what view goes on top
if (UIInterfaceOrientationIsLandscape(interfaceOrientation))
nextView = self.gridViewController.view;
else
nextView = self.tableViewController.view;
if (nextView == self.tableViewController.view)
{
if (!alreadyGoodTable)
{
self.tableViewController.view.alpha = 0.0;
[self.view bringSubviewToFront:self.tableViewController.view];
}
// Unhide the bar for the table view
[[UIApplication sharedApplication] setStatusBarHidden:NO withAnimation:UIStatusBarAnimationSlide];
}
else // gridViewController
{
if (!alreadyGoodGrid)
{
self.gridViewController.view.alpha = 0.0;
[self.view bringSubviewToFront:self.gridViewController.view];
}
// Hide the bar for the grid view
[[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation:UIStatusBarAnimationSlide];
}
[UIView animateWithDuration:0.4
delay: 0.0
options: UIViewAnimationOptionAllowUserInteraction
animations:^{
if (nextView == self.tableViewController.view) {
self.tableViewController.view.alpha = 1.0;
}
else {
self.gridViewController.view.alpha = 1.0;
}
}
completion:^(BOOL finished) {
if (nextView == self.tableViewController.view) {
curView = self.tableViewController.view;
}
else {
curView = self.gridViewController.view;
}
isAnimating = NO;
}];
}
}
Much thanks to anyone that can take the time to look at this.