Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I "legally" fade out the navigation bar in an app?

It seems the only way to remove a navigation bar with animation is via it sliding upward. I want it to fade, like in Photos.app.

It would be easiest to change the alpha, however Apple's guidelines state:

Prior to iOS v5.0, when used in conjunction with a navigation controller, there are only a handful of direct customizations you can make to the navigation bar. Specifically, it is alright to modify the barStyle, tintColor, and translucent properties, but you must never directly change UIView-level properties such as the frame, bounds, alpha, or hidden properties directly.

The language is a little weird, as it states prior to iOS 5, but it stated you're not allowed to change the alpha value directly, and it never states you're allowed to now.

I don't want my app to get rejected.

How do I fade out the navigation bar like I would the status bar?

like image 529
Doug Smith Avatar asked Jul 28 '13 22:07

Doug Smith


People also ask

How do I get rid of the transparent navigation bar?

How to remove opacity or transparency from sticky navigation/menu bar. If you want to remove the opacity or transparency from the sticky navigation bar, just navigate to Theme Options -> General -> Additional CSS and copy/paste this code and save changes.

How do I change the navigation bar on my Iphone?

A user changes the navigation bar's style, or UIBarStyle , by tapping the “Style” button to the left of the main page. This button opens an action sheet where users can change the background's appearance to default, black-opaque, or black- translucent.


2 Answers

This was a fun one to solve.

It should have been very straight-forward: use UIView transitionWithView to perform a cross-fade between the hidden and non-hidden states of the navigation bar, as set by the public API setNavigationBarHidden:animated:. In fact this works for "fading out" the navbar, but fading it back in had an issue. The issue was that the navbar would slide into place regardless of the fact that UIView +transitionWithView: doesn't animate animatable properties (e.g. frame) unless you specify UIViewAnimationOptionAllowAnimatedContent.

To me this says that internally the UINavigationController repositions the UINavigationBar inside an animation block regardless of whether animating was specified in the call to setNavigationBarHidden:animated:. The duration for this animation block is probably set to '0' when animate: is set to NO.

The solution is to set the navigation bar visible (sans animation) before the cross-fade transition. This ensures that the navigation bar begins the cross-fade in the correct position, and that the cross-fade will only reveal the new non-hidden state.

My sample project is a standard Single View Application. On the storyboard is a UINavigationController, which is the entry point. I set the bar style for this controller's UINavigationBar to black-translucent (similar to the Photos app). The navigation controller's rootViewController is a simple UIViewController with a UIImageView filling the entire bounds (also like the Photos app). I added a UITapGestureRecognizer on the view to invoke the following code, in the view controller:

- (IBAction) onShowHideNavbar: (id) sender
{
    BOOL hide = !self.navigationController.navigationBarHidden;

    if ( !hide)
    {
        [self.navigationController setNavigationBarHidden: hide animated: NO];
    }

    [UIView transitionWithView: self.navigationController.view
                      duration: 1
                       options: UIViewAnimationOptionTransitionCrossDissolve
                    animations: ^{

                        [self.navigationController setNavigationBarHidden: hide animated: NO];
                    }
                    completion: nil ];
}

All this said, I don't think you'd get into any trouble (Apple Rejection) for messing with the hidden or alpha properties of the UINavigationBar directly. The docs warn against touching these because they're managed by the UINavigationController and changing them might have unseen consequences. But In My Opinion they're public APIs and as such using them shouldn't be cause for rejection.

like image 200
TomSwift Avatar answered Oct 05 '22 18:10

TomSwift


You can't animate properties of the navigation bar of a UINavigationController legally.
However, you can show a navigation controller with hidden navigation bar (hiding it always or only on a specific view controller, as you prefer), and replace it with your "special" instance of UINavigationBar ;-)

I attach a sample project (I used an Xcode template to create it faster): FakeNavBar

Look at the viewDidLoad method of the DetailViewController:

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    [self configureView];

    self.fakeBar = [[UINavigationBar alloc]initWithFrame:self.navigationController.navigationBar.bounds];


    UIBarButtonItem *back = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemCancel target:self action:@selector(back)];



    UINavigationItem *backItem = [[UINavigationItem alloc]initWithTitle:@"Back"];
    backItem.leftBarButtonItem = back;
    [self.fakeBar pushNavigationItem:backItem animated:YES];

    [self.view addSubview:self.fakeBar];

}

Here's a video of the final product on YouTube.

like image 39
LombaX Avatar answered Oct 05 '22 19:10

LombaX