28

In Apple's recently released Remote app I noticed the way in which the navigation bar behaves is unique and I haven't been able reproduce it. When popping the Now Playing view controller the navigation bar remains transparent for the Now Playing view controller and the navigation bar for the library view controller also stays translucent (Screenshot 1). I'm trying to figure out if they are using two navigation controllers or only one. Personally I feel they're using just one for two reasons (1) the interactive pop gesture is enabled; (2) when you press the 'Now Playing' button in the library view controller, just before the now playing screen has finished 'push view controller' animation the navigation bar becomes transparent (Screenshot 2). This is the behaviour I experience when pushing my view controller (which sets the navigation bar to transparent). So my question is: How does Apple present both navigation bars of the two view controllers as if they were individual (as with Screenshot 1), even the bar buttons, navigation title etc... are 100% in opacity when switching (usually when pushing/popping the buttons and titles of the previous view controller fade as the new controller is being pushed). I've tried playing around with the bar tint colour in viewDidAppear and viewWillAppear in both view controllers but cannot reproduce the same behaviour, and cannot prevent the bar buttons from fading.

Gosh I hope I've explained this well, I get confused just thinking about it!

Screenshot 1 (Popping): Screenshot 1

Screenshot 2 (Pushing): Screenshot 2

sooper
  • 5,991
  • 6
  • 40
  • 65
  • Its nicely explained [here][1]. Read through. [1]: http://stackoverflow.com/questions/17074365/status-bar-and-navigation-bar-appear-over-my-views-bounds-in-ios-7 – Abhinav Nov 12 '13 at 00:45
  • @Abhinav Thanks but I don't see how that addresses my issue. I don't want an inset at the top. Like the Remote app, I want the table to scroll under the navigation bar but I also want to reproduce Screenshot 1 where all buttons, navigation bar tint colour, and titles are retained for both views during transition. – sooper Nov 12 '13 at 01:02
  • @LeoNatan appreciate that, just needed some free time to test it out. But if I can't try it before the bounty deadline I'll accept the answer before it. Cheers – sooper Dec 30 '13 at 23:14

2 Answers2

37

I just downloaded the application to make sure. Two different navigation bars are used. You can see this by using the interactive pop gesture. Notice how the navigation bar on the bottom view controller slides in and out. During normal push and pop transitions, the navigation items just fade in and out on the existing bar, while the bar is stationary. This is what happens up until the point where the now playing view controller is pushed.

If you look quickly, during the now playing view controller animation, you can see the bottom navigation bar disappear.

From my experience with UIKit behavior and what I see in the app, here is what I think happens:

album_vc = the bottom, list view controller nowplaying_vc = the top view controller

  • On nowplaying_vc's viewWillAppear:

    • Set the navigation bar to hidden using [self.navigationController setNavigationBarHidden:YES animated:YES];. Since this is in animation block, this will make the navigation bar slide out during the push animation.
    • Set [UIApplication sharedApplication].statusBarStyle = UIStatusBarStyleLightContent; Pretty sure about this, because notice there is no animation in the transition of the status bar styles. It just becomes white.
  • On nowplaying_vc's viewWillDisappear:

    • Set the navigation bar to shown using [self.navigationController setNavigationBarHidden:NO animated:YES];. Since this is in animation block, this will make the navigation bar slide in during the pop animation.
    • Set [UIApplication sharedApplication].statusBarStyle = UIStatusBarStyleDefault; Again, notice how during interactive pop gesture, the status bar just changes with no animation.

To achieve the transparent look of the navigation bar of nowplaying_vc, you can use an empty image ([UIImage alloc]) with setBackgroundImage:forBarPosition:barMetrics:.

Since the application does not rotate, we can't be sure if the navigation bar on nowplaying_vc is part of another navigation controller or just a navigation bar on the top with a position of UIBarPositionTopAttached. For all we know, there isn't even a navigation bar there but just a back chevron image view (back bar button is comprised of an image view and a button).

I think the status bar style is changed in viewWillAppear: and viewWillDisappear: due to the unnatural feel there is during interactive pop gesture. I would recommend using an animated transition, or even better, use the new view controller-based status bar style, which the system animates transitions by itself.


Update for modern API:

You should use the animateAlongsideTransition:completion: or animateAlongsideTransitionInView:animation:completion: API, rather than relying on the implicit animations of viewWillAppear: and viewWillDisappear:.

Léo Natan
  • 56,823
  • 9
  • 150
  • 195
  • cheers for that, didn't have time to try it out but will certainly get back to you when I do. – sooper Jan 01 '14 at 22:41
  • @sooper Please keep in touch. I am also interested in what happens. Thanks! – Léo Natan Jan 01 '14 at 22:45
  • I'm sure that this is the correct approach, but the only issue I'm having right now is that the interactive pop gesture is disabled when the navigation bar is hidden. So I can't use the pop gesture in `nowplaying_vc` in the way that the Remote app does. – sooper Jan 29 '14 at 14:47
  • @sooper You can certainly overcome that issue: http://keighl.com/post/ios7-interactive-pop-gesture-custom-back-button/. This should work with hidden navigation bar also. – Léo Natan Jan 29 '14 at 17:36
  • That did work. Unfortunately after playing around with this method I couldn't get the navigation bar to appear only in the `album_vc` when popping the `nowplaying_vc` like the Remote app. Gutted, I just can't figure it out. – sooper Mar 17 '14 at 13:03
  • 1
    @sooper Did you set it as hidden on `viewWillAppear:` (or disappear)? Set it hidden using `[self.navigationController setNavigationBarHidden:YES animated:YES];` – Léo Natan Mar 17 '14 at 13:56
  • setting `animated` to `YES` did it! I set hidden in `viewWillAppear:` and unset in `viewWillDisappear:` both animated. It's strange though, why would setting `animated` produce this behaviour? – sooper Mar 17 '14 at 15:15
  • @sooper My guess is, Apple has two implementations internally for setting the bar hidden, one for animated and one otherwise, and they reset the value during animation. I've seen weirder bugs/behaviors. With time you will learn the UIKit quirks. – Léo Natan Mar 17 '14 at 17:31
  • @sooper Updated the answer with the proper method of hiding the bar. – Léo Natan Mar 17 '14 at 17:34
3

Instead of hiding and showing the navigation bar, you can update the alpha for the navigation bar. It will animate smoothly during the transition. For the view controller with transparent nav bar, instead of modifying the nav bar, create a navbar (or just the back button and title etc.) manually in the second controller's view. We will then hide the navbar when transitioning from first view controller to the second one.

On your first controller's viewWillDisappear and on your second view controller's viewWillAppear:, set the navigation bar alpha to zero using self.navigationController.navigationBar.alpha = 0;. Since this is in animation block, this will make the navigation bar disappear during the push animation.

Set the alpha back to one in first controller's viewWillAppear and second controller viewWillDisappear.

Pulkit Goyal
  • 5,604
  • 1
  • 32
  • 50