How to draw a transparent UIToolbar or UINavigationBar in iOS7
Asked Answered
A

5

89

I would like an entirely transparent UIToolbar and/or UINavigationBar. I have tried the various incantations suggested for pre- and post-iOS 5 but none seem to work any more.

How might this be accomplished in iOS 7?

Anglicism answered 23/9, 2013 at 21:30 Comment(1)
For posterity - I was mistakenly using self.edgesForExtendedLayout = UIRectEdgeNone, which prevents the view extending under the toolbar.Anglicism
B
307

Swift 3 (iOS 10)

Transparent UIToolbar

self.toolbar.setBackgroundImage(UIImage(),
                                forToolbarPosition: .any,
                                barMetrics: .default)
self.toolbar.setShadowImage(UIImage(), forToolbarPosition: .any)

Transparent UINavigationBar

self.navigationBar.setBackgroundImage(UIImage(), for: .default)
self.navigationBar.shadowImage = UIImage()
self.navigationBar.isTranslucent = true

Swift < 3

Transparent UIToolbar

self.toolbar.setBackgroundImage(UIImage(),
                                forToolbarPosition: UIBarPosition.Any,
                                barMetrics: UIBarMetrics.Default)
self.toolbar.setShadowImage(UIImage(),
                            forToolbarPosition: UIBarPosition.Any)

Transparent UINavigationBar

self.navigationBar.setBackgroundImage(UIImage(), forBarMetrics: UIBarMetrics.Default)
self.navigationBar.shadowImage = UIImage()
self.navigationBar.translucent = true

Objective-C

Transparent UIToolbar

[self.toolbar setBackgroundImage:[UIImage new]
              forToolbarPosition:UIBarPositionAny
                      barMetrics:UIBarMetricsDefault];
[self.toolbar setShadowImage:[UIImage new]
          forToolbarPosition:UIBarPositionAny];

Transparent UINavigationBar

[self.navigationBar setBackgroundImage:[UIImage new]
                         forBarMetrics:UIBarMetricsDefault];
self.navigationBar.shadowImage = [UIImage new];
self.navigationBar.translucent = YES;

Discussion

Setting translucent to YES on the navigation bar does the trick, due to a behavior discussed in the UINavigationBar documentation. I'll report here the relevant fragment:

If you set this property to YES on a navigation bar with an opaque custom background image, the navigation bar will apply a system opacity less than 1.0 to the image.


Final result

final result

Bedtime answered 23/9, 2013 at 21:35 Comment(17)
Have you confirmed the toolbar version works on iOS7? I get a dark toolbar and a strange flickering on presentation.Anglicism
The screenshot is from the iOS 7 simulatorBedtime
Also I just run a test app on my iPhone 5 with iOS 7 and it works as expected.Bedtime
Thanks for the sanity check. I must be missing something else.Anglicism
Nicely done, so many wrong/bad ways to do this out there on SOJoni
I had to add translucent = YES to UIToolbar as well.Backstretch
Weird. I remember trying to change the translucent value of UIToolbar to YES/NO and it didn't affect the final result. Are you instantianing the toolbar from code or using a xib/storyboard?Bedtime
If using edgesForExtendedLayout = UIRectEdgeNone, you'll probably want to implement custom transitions. Because otherwise, when pushing views, the default transition will create a dark flicker under the transparent bar during animation. FYI, here's a quick resource for a basic sliding transition: gist.github.com/ArtFeel/7690431Thermostatics
I wish this worked only for one view not all of them. When placed in viewDidLoad in one view controller it will change it for all other viewsLeaguer
Note: if a toolbar is added to the scene, it is not referenced by self.navigationController.toolbar - this is the default one owned by the navigationController (see https://mcmap.net/q/176481/-visually-modifying-a-uitoolbar-from-xcode-storyboard).Playroom
@Kyle If you add a toolbar to your scene, then anything you do to it will only affect that toolbar. If you modify self.navigationController.toolbar then it affects all views in that navigation controller.Playroom
@GabrielePetronella, Why not use UIToolbarPositionAny instead of UIBarPositionAny for the transparent UIToolbar?Contrapuntist
@IulianOnofrei UIToolbarPosition is deprecated in favor of UIBarPosition since iOS 6.1Bedtime
@GabrielePetronella, 1) UIToolbarPosition is just a macro 2) Then why are you using in the next line of code?Contrapuntist
@IulianOnofrei overlook. There's not practical reason to prefer any of the two, but if one wants to be nitpicky UIToolbarPosition is deprecated.Bedtime
This doesn't work for me in Swift 2. I get this error: Value of type MyController has no member 'toolbar'.Saddleback
It worked for me without setting the shadow image. Is there a need to update the shadow too? Am I missing something? Would anything unexpected happen if I don't set it?Disturbed
E
8

If you want to do it through the entire app you should use the UIAppearance proxy (iOS5+):

UINavigationBar *navigationBarAppearance = [UINavigationBar appearance]; navigationBarAppearance.backgroundColor = [UIColor clearColor]; [navigationBarAppearance setBackgroundImage:[[UIImage alloc] init] forBarMetrics:UIBarMetricsDefault]; navigationBarAppearance.shadowImage = [[UIImage alloc] init];

Docs: https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIAppearance_Protocol/Reference/Reference.html

Article: http://nshipster.com/uiappearance/

Eam answered 31/1, 2014 at 7:29 Comment(2)
Just a note for people looking at this - put this code in your AppDelegate didFinishLaunchingWithOptions for a quick and dirty way to get this applied.Average
You can also set this appearance proxy to only work with specific UINavigationController subclasses—i.e., the ones that you want this behavior applied to.Mayne
S
2

Try:

[navBar setBackgroundImage:[UIImage alloc] forBarMetrics:UIBarMetricsDefault];
Staceestacey answered 23/9, 2013 at 21:40 Comment(0)
B
1
@implementation MyCustomNavigationBar

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        [self setup];
    }
    return self;
}

- (id)initWithCoder:(NSCoder *)aDecoder {
    self = [super initWithCoder:aDecoder];
    if (self) {
        [self setup];
    }
    return self;
}

- (void)setup {
    [self setupBackground];
}

- (void)setupBackground {
    self.backgroundColor = [UIColor clearColor];
    self.tintColor = [UIColor clearColor];

    // make navigation bar overlap the content
    self.translucent = YES; 
    self.opaque = NO;

    // remove the default background image by replacing it with a clear image
    [self setBackgroundImage:[self.class maskedImage] forBarMetrics:UIBarMetricsDefault];

    // remove defualt bottom shadow
    [self setShadowImage: [UIImage new]]; 
}

+ (UIImage *)maskedImage {
    const float colorMask[6] = {222, 255, 222, 255, 222, 255};
    UIImage *img = [UIImage imageNamed:@"nav-white-pixel-bg.jpg"];
    return [UIImage imageWithCGImage: CGImageCreateWithMaskingColors(img.CGImage, colorMask)];
}

@end
Bearish answered 8/10, 2013 at 9:13 Comment(0)
P
0

Something I stumbled upon is that if I created a subclassed UINavigationBar and then created an empty -(void)drawRect: method, I would get a transparent navigation bar. I only tested this in iOS 7.*, but it seemed to work!

Plafker answered 25/10, 2013 at 19:36 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.