12

In my app, I got a UINavigationController. Unfortunately, when I rotate the device and the interface orientation changes, the UINavigationBar doesn't change its height. In other iPhone applications, such as the Contacts.app, the navigation bar gets slightly less tall in landscape mode. It must be built-in, because if you take the navigation sample app from the XCode menu and add interface orientation to it, it does change the navigation bar's height properly.

How can I make the navigation bar resize like it does in all other iPhone apps I've seen?

Peter Hosey
  • 95,783
  • 15
  • 211
  • 370
ryyst
  • 9,563
  • 18
  • 70
  • 97

8 Answers8

19

I've done a little testing, and although I don't like the method, it's quite easy to do.

Having looked for a private method that may have worked, I couldn't find one. All I found was:

@property BOOL forceFullHeightInLandscape;

- (BOOL)isMinibar;

There is no setter for -isMinibar, so we can't set that. I guess that it returns a value based on its height. Also, forceFullHeightInLandscape was set to NO, however it still didn't adjust its height.

While changing the autoresizingMask to include UIViewAutoresizingFlexibleHeight, the view did resize to be smaller, but now it was too small. However, -isMinibar suddenly returned YES. So that made me think of just letting the view resize itself, adjusting it to the right height.

So there we go, a method that works, even without private API calls:

- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
    [self.navigationBar performSelector:@selector(sizeToFit) withObject:nil afterDelay:(0.5f * duration)];
}

One thing you'll have to deal with is that the views below the bar won't get adjusted to the smaller bar, so that there will be a gap between the bar and the views below. Easiest way to solve this is to add a container view, just like the case with a UINavigationController. You'd come up with something like:

- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
    [self performSelector:@selector(resizeViewsForNavigationBar) withObject:nil afterDelay:(0.5f * duration)];
}

- (void)resizeViewsForNavigationBar {
    [self.navigationBar sizeToFit];

    // Resize containerView accordingly.
    CGRect containerViewRect = self.containerView.frame;
    containerViewRect.origin.y = CGRectGetMaxY(self.navigationBar.frame);
    containerViewRect.size.height = CGRectGetMaxY(self.view.frame) - containerViewRect.origin.y;
    self.containerView.frame = containerViewRect;
}
Joost
  • 10,333
  • 4
  • 55
  • 61
  • Thanks for the answer, I can't test it right now but I'll report back once I tried it. Interestingly, the container view does resize correctly already, as if the navigation bar had become shorter like it should. – ryyst Aug 31 '10 at 07:15
  • I tried it out just now and it works perfectly! Since the container view already resizes correctly, I just need the `sizeToFit` call. – ryyst Sep 06 '10 at 16:35
  • That's great. You may want to send a bug report though, since you're using a default `UINavigationController` it should just work. The container already resizes properly so the `UINavigationBar` should too. – Joost Sep 06 '10 at 18:12
  • Slight variation on this fix that might help people today(this still happens in iOS10). This helps if you don't want to collapse into the status bar but still need to resize width. self.navigationBar.frame = CGRectMake(self.navigationBar.frame.origin.x, self.navigationBar.frame.origin.y, [self.navigationBar sizeThatFits:self.navigationBar.bounds.size].width, self.navigationBar.frame.size.height); – Gabe Sep 21 '16 at 05:08
2

Thanks to Joost I've added

@property BOOL forceFullHeightInLandscape;

to my custom UINavigationBar class. And set in :

-(id)initWithFrame:(CGRect)frame{
forceFullHeightInLandscape = YES;

Worked like a charm

Twingnu
  • 21
  • 1
2

Similar to Joost's answer, but putting the method in willAnimateRotationToInterfaceOrientation has a better animation effect than willRotateToInterfaceOrientation. (There's no animation delay)

- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
    [self.navigationBar sizeToFit];
}
Jeffrey Sun
  • 7,789
  • 1
  • 24
  • 17
2

I think the behavior you want only happens when a navigation controller ( which represents the bars (navigation or toolbar)), is added to the window in the app delegate or presented by a tab bar, etc.

You can add a navigation bar via IB or code, it doesn't mean you have a navigation controller. My opinion is, create a navigation controller and initialize it with the view controller you're working in. Probably when the view rotates, the nav bar will shrink a little, the way you like.

Hope this helps

Omer
  • 5,470
  • 8
  • 39
  • 64
1

I just had this error as well, and although it's probably not for the same reason I'd like to post it here to help anyone else that goofs.

If you're overriding any willRotateToInterface methods, remember to call super

I blanked on that, but once I saw the accepted answer it came to me.

Ratan Sebastian
  • 1,892
  • 14
  • 23
Terry
  • 11
  • 1
0

I think this one is kind of similar to you and they have the code snippet:

iPhone: UINavigationBar with buttons - adjust the height

Community
  • 1
  • 1
vodkhang
  • 18,639
  • 11
  • 76
  • 110
  • Are you sure the navigation bar height shrinking isn't built-in somehwere? – ryyst Aug 21 '10 at 16:12
  • It must be built-in, because if you take the navigation sample app from the XCode menu and add interface orientation to it, it does change the navigation bar's height properly. – ryyst Aug 21 '10 at 16:20
0

I just tried a few things just within Interface Builder and Xcode and as long as you use the UINavigationBarController as RootViewController it works as described - getting smaller. Did you change any things within the Controller itself or in parts of how the Controller is loaded? Especially concerning the firing of events? I had some bad expiriences with the UITabBarController in terms of breaking the proper messaging and got some 'interessting' view side effects. Just a try and a guess.

mic
  • 23
  • 2
  • Well, I am indeed using a UITabBarController as well. Other than that, I'm creating everything with code, without Interface Builder. – ryyst Sep 02 '10 at 07:41
  • Ah, ok, seeing it has already be answered I'm curious what if you just use a UITabBar programatically. Is it still not working than? I presume it is all contained within the RootViewController. Maybe it's not really a bug but not working properly with two Controllers. If you try to do it with the Interface Builder it won't go anyway, not allowing to mix up a NavigationBarController with an UITabBarController. – mic Sep 06 '10 at 18:23
-1
(void)viewWillLayoutSubviews {
      self.navigationItem.titleView.bounds = self.navigationController.navigationBar.bounds;
}
laaposto
  • 11,835
  • 15
  • 54
  • 71