Change the alpha value of the navigation bar

34,475

Solution 1

As I support Colin's answer, I want to give you an additional hint to customize the appearance of an UINavigationBar including the alpha.

The trick is to use UIAppearance for your NavigationBar. This enables you to assign an UIImage to your NavigationBar's backgroundImage. You can generate these UIImages programmatically and use for that UIColors and set the colors' alpha properties as you want. I've done this in one of my own applications and it works as expected.

Here I give you some code snippets:

  1. E.g. in your ..AppDelegate.m add these lines in didFinishLaunchingWithOptions:

    //create background images for the navigation bar
    UIImage *gradientImage44 = nil; //replace "nil" with your method to programmatically create a UIImage object with transparent colors for portrait orientation
    UIImage *gradientImage32 = nil; //replace "nil" with your method to programmatically create a UIImage object with transparent colors for landscape orientation
    
    //customize the appearance of UINavigationBar
    [[UINavigationBar appearance] setBackgroundImage:gradientImage44 forBarMetrics:UIBarMetricsDefault];
    [[UINavigationBar appearance] setBackgroundImage:gradientImage32 forBarMetrics:UIBarMetricsLandscapePhone];
    [[UINavigationBar appearance] setBarStyle:UIBarStyleDefault];
    
  2. Implement convenience methods to programmatically creates UIImage objects, e.g. create a new category for UIImage:

    //UIImage+initWithColor.h
    //
    #import <UIKit/UIKit.h>
    
    @interface UIImage (initWithColor)
    
    //programmatically create an UIImage with 1 pixel of a given color
    + (UIImage *)imageWithColor:(UIColor *)color;
    
    //implement additional methods here to create images with gradients etc.
    //[..]
    
    @end
    
    //UIImage+initWithColor.m
    //
    #import "UIImage+initWithColor.h"
    #import <QuartzCore/QuartzCore.h>
    
    @implementation UIImage (initWithColor)
    
    + (UIImage *)imageWithColor:(UIColor *)color
    {
        CGRect rect = CGRectMake(0, 0, 1, 1);
    
        // create a 1 by 1 pixel context 
        UIGraphicsBeginImageContextWithOptions(rect.size, NO, 0);
        [color setFill];
        UIRectFill(rect);
    
        UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
    
        return image;
    }
    
  3. Re-work your image creation in 1. (#import "UIImage+initWithColor.h" in AppDelegate.m and replace the "nil"s):

This is your spot of interest: by changing your colors' alpha property you are influencing the opacity level of you NavigationBar as well!

            UIImage *gradientImage44 = [UIImage imageWithColor:[UIColor colorWithRed:1.0 green:0.0 blue:1.0 alpha:0.2]];
            UIImage *gradientImage32 = [UIImage imageWithColor:[UIColor colorWithRed:1.0 green:0.0 blue:1.0 alpha:0.2]];

I created a small demo project and add you two screenshots: the view itself has a yellow backgroundColor. The backgroundImages of the NavigationBar have a red color. Screenshot 1 shows a NavigationBar with a value for alpha = 0.2. Screenshot 2 shows a NavigationBar with a value for alpha = 0.8.

Screenshot for NavigationBar with alpha=0.2 Screenshot for NavigationBar with alpha=0.8

Solution 2

The most straightforward way of doing this is modifying the alpha component of navigationBar background view, which at this time (iOS9) is a first navigationBar subview. Note however that we never know if the subview hierarchy will be changed by apple in later releases, so gotta be careful.

let navigationBackgroundView = self.navigationController?.navigationBar.subviews.first
navigationBackgroundView?.alpha = 0.7

Solution 3

Directly from the Apple Developer reference:

"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."

You can however set the translucence property of the navigation bar. If you do [self.navigationController.navigationBar setTranslucent:YES]; should solve your problem. You can also try seeing if any of the UIBarStyle enums are something you want.

Solution 4

MickBraun's answer in Swift:

  1. In AppDelegate.swift add these lines in didFinishLaunchingWithOptions:

    // create background images for the navigation bar
    let gradientImage44 = UIImage.imageWithColor(UIColor(red: 1.0, green: 0.0, blue: 1.0, alpha: 0.2))
    let gradientImage32 = UIImage.imageWithColor(UIColor(red: 1.0, green: 0.0, blue: 1.0, alpha: 0.2))
    
    // customize the appearance of UINavigationBar
    UINavigationBar.appearance().setBackgroundImage(gradientImage44, forBarMetrics: .Default)
    UINavigationBar.appearance().setBackgroundImage(gradientImage32, forBarMetrics: .Compact)
    UINavigationBar.appearance().barStyle = .Default
    
  2. Implement convenience methods to programmatically create UIImage objects.

    class func imageWithColor(colour: UIColor) -> UIImage {
        let rect = CGRectMake(0, 0, 1, 1)
    
        // Create a 1 by 1 pixel content
        UIGraphicsBeginImageContextWithOptions(rect.size, false, 0.0)
        colour.setFill()
        UIRectFill(rect)
    
        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
    
        return image
    }
    

Solution 5

You have a few options depending, in part, upon the barStyle of your UINavigationBar. The main thing is realizing that you likely don't necessarily have to animate the alpha property to get the effect you're describing.

UIBarStyleDefault or UIBarStyleBlackOpaque Option A is to set your UINavigationBar translucent property to YES, then animate the alpha:

            navigationBar.translucent = YES; // ideally set this early, in the nib/storyboard, or viewDidLoad

...

            [UIView animateWithDuration: 1.0
                             animations: ^{

                                 // toggle:
                                 navigationBar.alpha = navigationBar.alpha == 0 ? 1.0 : 0.0;

                             }];

In this scenario your view will be positioned behind your navbar, even when its alpha is 1.0. The downside to this scenario is that even with a 1.0 alpha you might see a tinge of your view's background color behind the UINavigationBar. Also, all of your subviews will need to be positioned 44 points down from the top.

UIBarStyleDefault or UIBarStyleBlackOpaque Option B is to hide the navbar in a cross-disolve transition animation. This will expose the superview of the UINavigationBar. If you're using a UINavigationController then the black background of the UINavigationController view is what you'll see - but you can set the background color of the UINavigationController view to match your view to get the effect that you want:

    UINavigationBar* navigationBar = self.navigationController.navigationBar;

    self.navigationController.view.backgroundColor = self.view.backgroundColor;
    [UIView transitionWithView: navigationBar
                      duration: 1.0
                       options: UIViewAnimationOptionTransitionCrossDissolve
                    animations: ^{
                        // toggle:
                        navigationBar.hidden = !navigationBar.hidden;
                    }
                    completion: nil];

One thing to watch out for with this solution might be a layout issue if the UINavigationController updates your view frame because you hid the UINavigationBar. This would be fine except that your subviews might shift up 44 pixels if they're anchored to the top left. To work around this you might consider anchoring your subviews to the bottom of your view instead (either with springs or with layout constraints).

UIBarStyleDefault or UIBarStyleBlackOpaque Option C is to cover up the UINavigationBar with another view, again using a cross-disolve transition animation:

        UINavigationBar* navigationBar = self.navigationController.navigationBar;

        [UIView transitionWithView: navigationBar
                          duration: 1.0
                           options: UIViewAnimationOptionTransitionCrossDissolve | UIViewAnimationOptionAllowAnimatedContent
                        animations: ^{

                            // toggle:
                            const int tag = 1111; 
                            UIView* navOverlayView = [navigationBar viewWithTag: tag];
                            if ( navOverlayView == nil )
                            {
                                navOverlayView = [[UIView alloc] initWithFrame: CGRectInset( navigationBar.bounds, 0, -3 ) ];
                                navOverlayView.backgroundColor = self.view.backgroundColor;
                                navOverlayView.tag = tag;
                                [navigationBar addSubview: navOverlayView];
                            }
                            else
                            {
                                [navOverlayView removeFromSuperview];
                            }
                        }
                        completion: nil];

UIBarStyleBlackTranslucent: This option is the easiest, as the UINavigationBar is already translucent, and your view is already behind it. Simply animate the alpha:

    [UIView animateWithDuration: 1.0
                     animations: ^{

                         // toggle:
                         navigationBar.alpha = navigationBar.alpha == 0 ? 1.0 : 0.0;

                     }];
Share:
34,475
Doug Smith
Author by

Doug Smith

I'm a web designer playing around with iOS from England

Updated on July 25, 2020

Comments

  • Doug Smith
    Doug Smith almost 4 years

    Is this possible?

    I want to change the alpha value of the navigation bar in my view controller (in an animation), but if I do self.navigationController.navigationBar.alpha = 0.0;, the portion of the screen the navigationBar took up totally disappears and leaves a black box, which is not what I'd like (I'd prefer it to be the color of self.view's background).

  • Doug Smith
    Doug Smith almost 11 years
    The translucent option doesn't work, it seems to just make the navigation bar slightly lighter.
  • Doug Smith
    Doug Smith almost 11 years
    This changes the color of the status bar from black to grey. :/
  • Danilo
    Danilo almost 11 years
    which one of the 3 methods?
  • Can
    Can almost 11 years
    @DougSmith Yeah, but Doug, when you set the bar as translucent, then the view gets resized to use the whole screen (sans status bar), so if you do an animation with self.navigationController.navigationBar.alpha = 0.0; it will work as you intended, the content of the view will be rendered on behind the status bar. Just tried it out in a throwaway project and it worked.
  • Rob van der Veer
    Rob van der Veer almost 11 years
    Also remember that if you set translucent to YES, you will have to adjust the frame of your view because it will shift up to cover the space below the navigation bar (that has now become transparent).
  • natec
    natec over 8 years
    The last line in part 1 is actually UINavigationBar.appearance().barStyle = .Default, at least with Swift 2 and iOS 9.
  • johndpope
    johndpope over 6 years
    yes - @RobvanderVeer - this seems to fix things self.edgesForExtendedLayout = []