11

On iOS 7, if I use the prefersStatusBarHidden method and return an instance variable that can be changed:

- (BOOL)prefersStatusBarHidden {
    return self.statusBarShouldBeHidden;
}

And I change the instance variable, thus hiding the status bar, the navigation bar loses the 20pt of height that the status bar occupies. I don't want this, however. Is it possible to hide the status bar but keep the height of the navigation bar?

Doug Smith
  • 29,668
  • 57
  • 204
  • 388
  • 1
    https://github.com/molon/MMDrawerController/blob/master/MMDrawerController/MLSwipeDrawerController/UINavigationBar%2BFixFrameAfterHideStatusBar.m The link will help you. You just need pay attetion to [UINavigationBar+FixFrameAfterHideStatusBar] category. – molon Nov 22 '14 at 15:03

3 Answers3

8

I found one solution to this problem at the following blogpost: http://www.factorialcomplexity.com/blog/2014/08/05/fixed-height-navigation-bar-on-ios7.html but his solution uses method swizzling on UINavigationBar, which I find unappealing.

UPDATE:

I figured out that subclassing UINavigationBar and providing a similar implementation to the swizzled solution solves this problem (Swift here, but the same works in Obj-C):

class MyNavigationBar: UINavigationBar {
    override func sizeThatFits(size: CGSize) -> CGSize {
        var size = super.sizeThatFits(size)
        if UIApplication.sharedApplication().statusBarHidden {
            size.height = 64
        }
        return size
    }
}

Then update the class of the Navigation Bar in your storyboard, or use initWithNavigationBarClass:toolbarClass: when constructing your navigation controller to use the new class.

Alex Pretzlav
  • 15,505
  • 9
  • 57
  • 55
  • Very clean and simple solution, thanks a lot! Even animating the status bar out still looks great. – wolfrevo Jul 25 '15 at 11:32
  • 3
    Hey Alex and @Seabass I'm using this solution and it's working great but the title and the navigation buttons have some weird animations. They jump down and animate up when showing the status bar. and the opposite when I hide it. Any ideas how to fix this? – Eeshwar Dec 07 '15 at 21:45
2

The navigation bar is keeping its height, it's just that the navigation bar and status bar don't have any separator between them (and have the same background), so they appear to be one thing, when, in fact, they are two. So what you really want is for the navigation bar to expand to take up the space previously occupied by both the navigation bar and the status bar.

I've done it like this before (heightCon is an IBOutlet to a height constraint on the navigation bar).

-(IBAction)hideStatusBar:(id)sender {
    static BOOL hidden = YES;
    [[UIApplication sharedApplication] setStatusBarHidden:hidden withAnimation:UIStatusBarAnimationSlide];
    self.heightCon.constant = (hidden)? 64 : 44;
    [UIView animateWithDuration:0.35 animations:^{
        [self.navBar layoutIfNeeded];
    }];
    hidden = ! hidden;
}
rdelmar
  • 103,982
  • 12
  • 207
  • 218
  • How are you able to hide the status bar in that fashion? I've only been able to with the above method. – Doug Smith Dec 10 '13 at 15:30
  • @DougSmith, I also added an entry to the info.plist file, "View Controller-based status bar appearance" with a value of NO. This allows you to toggle it off and on with the above code. – rdelmar Dec 10 '13 at 15:45
  • @rdelmar, The navigation bar will shrink to 44 px and vice versa according to the status bar visuality. You can add this chunk of code to have a better understating how it works. You will see the image shrinking. `[self.navigationController.navigationBar setBounds:CGRectMake(0, -50, 320,0)];[self.navigationController.navigationBar setBackgroundImage:[UIImage imageNamed:@"navbar"] forBarPosition:UIBarPositionTopAttached barMetrics:UIBarMetricsDefault];` – Segev Jan 09 '14 at 06:55
  • Still, if we'll print the navbar frame height before and after the hidden statusbar we will get 44 px in both cases but visually that's not the case. It's more clear if you'll move the navbar to the middle of the screen. – Segev Jan 09 '14 at 06:56
0

I didn't get @rdelmar solution to work for me with the NSLayoutConstraint but I used his idea to come up with this very simple code.

[[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation:UIStatusBarAnimationSlide];
[UIView animateWithDuration:0.35
                      delay:0
                    options:UIViewAnimationOptionBeginFromCurrentState
                 animations:^{
                             self.navigationBar.top = 20;
                 }
                 completion:nil];

The options:UIViewAnimationOptionBeginFromCurrentState is very important here otherwise the animation is jerky because it starts from 0.

apouche
  • 9,703
  • 6
  • 40
  • 45
  • 2
    From my experience you can't set the value of struct the way you are with `navigationBar.top`. Is this just an illustration to show what you are doing there without including a lot of CGRect Code? – Shawn Throop Sep 12 '14 at 19:37