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?

Gabriele Petronella
  • 106,943
  • 21
  • 217
  • 235
Ben Packard
  • 26,102
  • 25
  • 102
  • 183
  • For posterity - I was mistakenly using self.edgesForExtendedLayout = UIRectEdgeNone, which prevents the view extending under the toolbar. – Ben Packard Sep 24 '13 at 01:04

5 Answers5

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

Community
  • 1
  • 1
Gabriele Petronella
  • 106,943
  • 21
  • 217
  • 235
  • 1
    Have you confirmed the toolbar version works on iOS7? I get a dark toolbar and a strange flickering on presentation. – Ben Packard Sep 23 '13 at 23:23
  • 2
    The screenshot is from the `iOS 7` simulator – Gabriele Petronella Sep 23 '13 at 23:25
  • Also I just run a test app on my iPhone 5 with iOS 7 and it works as expected. – Gabriele Petronella Sep 23 '13 at 23:27
  • Thanks for the sanity check. I must be missing something else. – Ben Packard Sep 23 '13 at 23:28
  • 1
    Nicely done, so many wrong/bad ways to do this out there on SO – pfrank Sep 29 '13 at 03:50
  • I had to add translucent = YES to UIToolbar as well. – atomkirk Oct 15 '13 at 17:38
  • 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? – Gabriele Petronella Oct 15 '13 at 17:45
  • 2
    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: https://gist.github.com/ArtFeel/7690431 – anna Dec 14 '13 at 16:21
  • 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 views – Kyle Greenlaw Jan 09 '14 at 00:30
  • 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 http://stackoverflow.com/a/8753847/481207). – Matt Dec 09 '14 at 19:46
  • @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. – Matt Dec 09 '14 at 19:47
  • @GabrielePetronella, Why not use `UIToolbarPositionAny` instead of `UIBarPositionAny` for the transparent `UIToolbar`? – Iulian Onofrei Sep 14 '15 at 12:18
  • @IulianOnofrei `UIToolbarPosition` is deprecated in favor of `UIBarPosition` since iOS 6.1 – Gabriele Petronella Sep 14 '15 at 13:17
  • @GabrielePetronella, 1) `UIToolbarPosition` is just a macro 2) Then why are you using in the next line of code? – Iulian Onofrei Sep 14 '15 at 15:26
  • @IulianOnofrei overlook. There's not practical reason to prefer any of the two, but if one wants to be nitpicky `UIToolbarPosition` is deprecated. – Gabriele Petronella Sep 14 '15 at 15:27
  • This doesn't work for me in Swift 2. I get this error: Value of type MyController has no member 'toolbar'. – Prabhu Oct 08 '16 at 20:23
  • 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? – Abdurrahman Mubeen Ali Oct 25 '17 at 13:14
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/

Adam Waite
  • 19,175
  • 22
  • 126
  • 148
  • 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. – Shaun Dec 04 '14 at 05:02
  • 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. – Evan R Aug 20 '20 at 03:51
2

Try:

[navBar setBackgroundImage:[UIImage alloc] forBarMetrics:UIBarMetricsDefault];
Léo Natan
  • 56,823
  • 9
  • 150
  • 195
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
yelled
  • 19
  • 2
  • 5
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!

jakenberg
  • 2,125
  • 20
  • 38