2

I created a subclass of UITabBarController, in order to hide tabBar and statusBar once in landscape mode. I successfully implemented the code to hide/show the tabBar, but the stausBar is driving me crazy. My current implementation works 100% but not for the first rotation, and I'm unable to figure out why. The code is the following:

- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
  BOOL hide = (fromInterfaceOrientation == UIInterfaceOrientationPortrait || 
                         fromInterfaceOrientation == UIInterfaceOrientationPortraitUpsideDown);
  [[UIApplication sharedApplication] setStatusBarHidden:hide withAnimation:UIStatusBarAnimationNone];
  CGRect mainFrame = [[UIScreen mainScreen] applicationFrame];
  [self.view setFrame:mainFrame];
}

In practice the first time I rotate my iPhone, the statusBar is correctly hide, but the frame is not correct (it has the 20px gap on the top). If I return to the portrait view from here, the layout will restore as expected, if then I rotate in landscape for the second time it will finally works as desired (no bars, pixel perfect layout!)... and from this point I can rotate my device N times and the views will always be presented in the right way... so, why the first time my code fails?!

Extra info you may need:

  • root tab controllers are UINavigationControllers
  • all my nested view controllers are properly configured to support orientation changes
  • I'm testing using iOS 5
daveoncode
  • 18,900
  • 15
  • 104
  • 159

2 Answers2

5

I can't believe it, but the solution is really simple! I solved by moving setStatusBarHidden:withAnimation: from didRotate... to willRotate..., the implementation is the following:

- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
  BOOL show = (toInterfaceOrientation == UIInterfaceOrientationPortrait || 
                 toInterfaceOrientation == UIInterfaceOrientationPortraitUpsideDown);
  [[UIApplication sharedApplication] setStatusBarHidden:!show withAnimation:UIStatusBarAnimationNone];
}

In my case there is no need to hardcoding the new frame, since my views make use of autoresize masks... the view will be rendered properly automagically by UIKit... AWESOME :)

... +1 to virushuo for citing willRotateToInterfaceOrientation (which I was not taking into account)

daveoncode
  • 18,900
  • 15
  • 104
  • 159
  • 1
    If you don't get "setStatusBarHidden" to work on iOS7, add the raw plist value "UIViewControllerBasedStatusBarAppearance" and set it to "NO". It's described here: http://stackoverflow.com/questions/18059703/cannot-hide-status-bar-in-ios7 – Vanja Feb 11 '14 at 15:16
  • Only `didRotateFromInterfaceOrientation` helps me on iOS 8. – Dmitry Nov 23 '14 at 21:59
  • The best result is with `willAnimateRotationToInterfaceOrientation`. No blinking on the first rotation. – Dmitry Nov 23 '14 at 22:04
2

Try UINavigationController class method setNavigationBarHidden:animated: in willRotateToInterfaceOrientation.

setNavigationBarHidden:animated: Sets whether the navigation bar is hidden.

  • (void)setNavigationBarHidden:(BOOL)hidden animated:(BOOL)animated Parameters hidden Specify YES to hide the navigation bar or NO to show it. animated Specify YES if you want to animate the change in visibility or NO if you want the navigation bar to appear immediately. Discussion For animated transitions, the duration of the animation is specified by the value in the UINavigationControllerHideShowBarDuration constant.

Availability Available in iOS 2.0 and later.

http://developer.apple.com/library/ios/#documentation/uikit/reference/UINavigationController_Class/Reference/Reference.html

virushuo
  • 660
  • 3
  • 5