alexgophermix alexgophermix - 3 months ago 95
Objective-C Question

How to transition smoothly from translucent to opaque UINavigationBar iOS?

I'm running into problems reconfiguring the

on iOS 7 and 8 when transitioning between views.

My application currently contains the following

VC1 --> VC2 --> VC3

In this flow

  • VC1 is the home screen and has an opaque

  • VC2 has a translucent

  • VC3 goes back to having an opaque

The problem I've been running into is that the transitions between these views are all very sloppy looking. To start with I tried the following:

in VC2

- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];

// configure appearance
[self.navigationController.navigationBar configureTranslucentAppearance];

And in VC1 and VC3

- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];

// configure appearance
[self.navigationController.navigationBar restoreDefaultAppearance];

Here are the implementations of the two helper functions listed above:

- (void)restoreDefaultAppearance {
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];

[self setTitleTextAttributes:@{NSForegroundColorAttributeName: [UIColor JTTextNavBar]}];
[self setTintColor:[UIColor JTTextNavBar]];
[self setBarTintColor:[UIColor JTBackgroundNavBarWithAlpha:1.0]];
[self setBackgroundImage:nil forBarMetrics:UIBarMetricsDefault];
[self setBackgroundColor:[UIColor JTBackgroundNavBarWithAlpha:1.0]];
[self setShadowImage:[UIImage navigationBarShadowImage]];
[self setTranslucent:NO];

- (void)configureTranslucentAppearance {
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];

[self setBackgroundImage:[UIImage new] forBarMetrics:UIBarMetricsDefault];
[self setBackgroundColor:[UIColor clearColor]];
[self setShadowImage:[UIImage new]];
[self setTranslucent:YES];

This is the most basic way of handling this transition. It has the following visual artefacts:

  • When going from VC1 --> VC2 the moment you begin the transition the navigation bar turns black. The animation completes normally enter image description here

  • When going from VC2 --> VC1 the nav bar instantly changes to the application default colour before the segue has time to complete. enter image description here

  • When going from VC2 --> VC3 the navigation bar instantly goes from translucent to the app nav bar color and then menu items and VC body animate in. enter image description here

  • When going from VC3 --> VC2 the nav bar instantly turns black and remains this way until the segue is complete. enter image description here

None of these transitions look good at all. Ideally I would like the views to transition smoothly along with their new
but the only way I've seen to do this successfully is to manually add a toolbar to each xib.

Any suggestions? Apologies if this description is confusing :(

Edit: Added cropped images of the
and top portion of
for each of the listed transitions.


I finally found a decent solution!

There doesn't appear to be a proper way to smoothly transition from an opaque to transparent UINavigationBar BUT you can transition smoothly from a view controller with a visible status bar to one that has a hidden status bar.

This opens up a possible workaround which is to add the following in the viewWillAppear of VC2 from above:

[self.navigationController setNavigationBarHidden:YES animated:YES];

Once you have that, manually add a UINavigationBar to your xib and configure it to be transparent (and add all necessary UIBarButtonItem and views).

If everything is hooked up properly transitioning from VC1 to VC2 will hide the UINavigationBar at the same speed as the view transition and VC2 will show up with it's embedded UINavigationBar

Note: To make this work properly you'll have to make sure that in the viewWillAppear of View Controllers that can be accessed from VC2 you reset the UINavigationBar to be visible (if necessary) via:

[self.navigationController setNavigationBarHidden:NO animated:YES];

TL;DR - manually add a UINavigationBar to your transparent nav bar view controller and in its viewWillAppear hide the default one via setNavigationBarHidden:animated: