247

How do you make a UINavigationBar transparent? Though I want its bar items to remain visible.

Bhavin Bhadani
  • 22,224
  • 10
  • 78
  • 108
quano
  • 18,812
  • 25
  • 97
  • 108

20 Answers20

651

If anybody is wondering how to achieve this in iOS 7+, here's a solution (iOS 6 compatible too)

In Objective-C

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

In swift 3 (iOS 10)

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

In swift 2

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

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.

Community
  • 1
  • 1
Gabriele Petronella
  • 106,943
  • 21
  • 217
  • 235
  • 29
    Answering my own comment here; to undo the affect try:`[self.navigationController.navigationBar setBackgroundImage:nil forBarMetrics:UIBarMetricsDefault]; self.navigationController.navigationBar.shadowImage = nil; self.navigationController.navigationBar.translucent = NO;` – Johann Burgess Jan 05 '15 at 02:10
  • I need only one VC to have a transparent navbar. How do I revert to the original style after exiting that VC? – Guilherme Feb 06 '15 at 19:16
  • 2
    to achieve this in Swift from within a ViewController, do it like this: `self.navigationController?.navigationBar.setBackgroundImage(UIImage(), forBarMetrics: UIBarMetrics.Default) self.navigationController?.navigationBar.shadowImage = UIImage() self.navigationController?.navigationBar.translucent = true` – dy_ Mar 03 '15 at 15:01
  • Works using appeareance as well (iOS7/8), see : https://gist.github.com/mpycio/ddbdea1adb6b86cf02f6 – Mahakala Mar 05 '15 at 14:56
  • If anyone is wondering, you can undo the effect in Swift the same way -- in spite of the fact the function takes `UIImage!` as an argument, sending nil works. – jab Mar 27 '15 at 18:03
  • Works with Appearance proxy in iOS 9 – user3099609 Feb 10 '16 at 10:31
  • 1
    Undoing the effect for me only partially works. Because after I do this, my tableviews all have headers that are too large. App-wide, which is weird. (I only want this effect for one controller that I push on the stack.) – Henning May 11 '16 at 15:58
  • if need a percentage how should be? – jose920405 May 17 '16 at 22:01
  • For me, in iOS9, and as mentioned lower down, remove 1 line (has no effect that I can see) and add another: `[self.navigationController.navigationBar setBackgroundImage:[UIImage new] forBarMetrics:UIBarMetricsDefault]; [self.navigationController.navigationBar setBackgroundColor:[UIColor clearColor]]; //self.navigationController.navigationBar.shadowImage = [UIImage new]; self.navigationController.navigationBar.translucent = YES;` – ghr Oct 27 '16 at 12:41
  • Setting `translucent` to `NO` works for me in iOS 10.2 – Iulian Onofrei Jan 26 '17 at 14:59
  • @Stone Currently struggling with exactly this issue, have you been able to solve it? – Mario Aug 05 '18 at 12:17
  • @Mario unfortunately no. Our workaround was to make the `NavigationBar` transparent by default and work with a background image. Have a look at this: https://stackoverflow.com/a/48691715/2307466 – Stone Aug 06 '18 at 07:25
  • 1
    You'll need `navigationBar.standardAppearance.backgroundEffect = nil` too in newer iOS verisons – Sam Soffes Feb 23 '21 at 18:14
30

In iOS5 you can do this to make the navigation bar transparent:

nav.navigationBar.translucent = YES; // Setting this slides the view up, underneath the nav bar (otherwise it'll appear black)
const float colorMask[6] = {222, 255, 222, 255, 222, 255};
UIImage *img = [[UIImage alloc] init];
UIImage *maskedImage = [UIImage imageWithCGImage: CGImageCreateWithMaskingColors(img.CGImage, colorMask)];

[nav.navigationBar setBackgroundImage:maskedImage forBarMetrics:UIBarMetricsDefault]; 
[img release];
Community
  • 1
  • 1
Alex Stanciu
  • 5,183
  • 2
  • 24
  • 31
  • 6
    In iOS 6 you will also want to remove the navigation bar shadow, otherwise it will look strange. `[[UINavigationBar appearance] setShadowImage: [[UIImage alloc] init]];` – Robert May 26 '13 at 20:59
23

From IOS7 :

self.navigationController.navigationBar.translucent = YES;
self.navigationController.navigationBar.shadowImage = [UIImage new];
self.navigationController.view.backgroundColor = [UIColor clearColor];
[self.navigationController.navigationBar setBackgroundImage:[UIImage new] forBarMetrics:UIBarMetricsDefault];
self.navigationController.navigationBar.backgroundColor = [UIColor clearColor];
Kane Cheshire
  • 1,654
  • 17
  • 20
Damien Romito
  • 9,801
  • 13
  • 66
  • 84
17

If you build with the latest beta iOS 13.4 and Xcode 11.4, the accepted answer won't work anymore. I've found another way, maybe it's just a bug in the beta software, but I'm writing it down there, just in case

(swift 5)

import UIKit

class TransparentNavBar :UINavigationBar {
    override func awakeFromNib() {
        super.awakeFromNib()
        self.setBackgroundImage(UIImage(), for: .default)
        self.shadowImage = UIImage()
        self.isTranslucent = true
        self.backgroundColor = .clear
        if #available(iOS 13.0, *) {
            self.standardAppearance.backgroundColor = .clear
            self.standardAppearance.backgroundEffect = .none
            self.standardAppearance.shadowColor = .clear
        }
    }
}
shim
  • 9,289
  • 12
  • 69
  • 108
Federico Picci
  • 1,105
  • 10
  • 17
  • Awesome! Was just searching for a fix! Works great! Thanks! – Georg Mar 26 '20 at 15:30
  • Thank you! Note that if you're already setting `standardAppearance` via `UIAppearance`, setting the `backgroundColor`/`backgroundEffect`/`shadowColor` as shown here may not work, because `UINavigationBarAppearance` properties do not work with `UIAppearance`. Instead, you need to make your own instance of `UINavigationBarAppearance`, set the properties as you like, then set `navigationBar.standardAppearance = myNewInstance`. – nolanw Mar 04 '21 at 21:22
14

For anyone who wants to do this in Swift 2.x:

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

or Swift 3.x:

self.navigationController?.navigationBar.setBackgroundImage(UIImage(), for: .default)
self.navigationController?.navigationBar.shadowImage = UIImage()
self.navigationController?.navigationBar.isTranslucent = true
Antonio
  • 71,651
  • 11
  • 148
  • 165
gotnull
  • 26,454
  • 22
  • 137
  • 203
  • 2
    navigationController is an optional property so you need to unwrap it. Simply add self.navigationController?.navigationBar and you are good to go – Daniel Galasko Feb 06 '15 at 09:56
10

This seems to work:

@implementation UINavigationBar (custom)
- (void)drawRect:(CGRect)rect {}
@end

navigationController.navigationBar.backgroundColor = [UIColor clearColor];
Titouan de Bailleul
  • 12,920
  • 11
  • 66
  • 121
quano
  • 18,812
  • 25
  • 97
  • 108
  • 6
    It seems that in iOS 5 you must override `-drawRect:` in a subclass proper, not in a category, and then use this subclass as your navigation bar. – Yang Meyer Dec 08 '11 at 07:04
9

After doing what everyone else said above, i.e.:

navigationController?.navigationBar.setBackgroundImage(UIImage(), forBarMetrics: .default)
navigationController?.navigationBar.shadowImage = UIImage()
navigationController!.navigationBar.isTranslucent = true

... my navigation bar was still white. So I added this line:

navigationController?.navigationBar.backgroundColor = .clear

... et voila! That seemed to do the trick.

Clay Ellis
  • 4,960
  • 2
  • 37
  • 45
5

The below code expands upon the top answer chosen for this thread, to get rid of the bottom border and set text color:

  1. The last two coded lines of this code set transparency. I borrowed that code from this thread and it worked perfectly!

  2. The "clipsToBounds" property was code I found which got rid of the bottom border line with OR without transparency set (so if you decide to go with a solid white/black/etc. background instead, there will still be no border line).

  3. The "tintColor" line (2nd coded line) set my back button to a light grey

  4. I kept barTintColor as a backup. I don't know why transparency would not work, but if it doesn't, I want my bg white as I used to have it

    let navigationBarAppearace = UINavigationBar.appearance()
    navigationBarAppearace.tintColor = UIColor.lightGray
    navigationBarAppearace.barTintColor = UIColor.white
    navigationBarAppearace.clipsToBounds = true
    navigationBarAppearace.isTranslucent = true
    navigationBarAppearace.setBackgroundImage(UIImage(), for: .default)
    navigationBarAppearace.shadowImage = UIImage()
    
neoneye
  • 50,398
  • 25
  • 166
  • 151
Dave G
  • 12,042
  • 7
  • 57
  • 83
5

I know this topic is old, but if people want to know how its done without overloading the drawRect method.

This is what you need:

self.navigationController.navigationBar.translucent = YES;
self.navigationController.navigationBar.opaque = YES;
self.navigationController.navigationBar.tintColor = [UIColor clearColor];
self.navigationController.navigationBar.backgroundColor = [UIColor clearColor];
Sander
  • 75
  • 1
  • 1
  • 1
    Im sorry, this isn't correct. You still have to override the drawRect method – Sander Jun 21 '11 at 13:39
  • Why is this wrong? It seems to be working in IOS 6 sim. It isn't working in IOS 5? navigationBar.backgroundColor seems to be undocumented. – Cristi Dec 03 '12 at 12:48
4

Solution - Swift 5 - iOS 13+

According to the documentation, in your UIViewController subclass:

override func viewDidLoad()
{
    super.viewDidLoad()
    
    let appearance = UINavigationBarAppearance()
    appearance.configureWithTransparentBackground()
    //appearance.backgroundColor = UIColor.clear
    
    navigationItem.compactAppearance = appearance
    navigationItem.scrollEdgeAppearance = appearance
    navigationItem.standardAppearance = appearance
    
    //...
}

Just to be clear, this makes the UINavigationBar completely transparent. The bar button items are still visible and work properly.

What didn't work

override func viewDidLoad()
{
    super.viewDidLoad()
    
    navigationController?.navigationBar.isTranslucent = true
    navigationController?.navigationBar.isOpaque = false

    //...
}

This made me realize I didn't actually know the difference between transparent and translucent RIP.

References

https://developer.apple.com/documentation/uikit/uinavigationcontroller/customizing_your_app_s_navigation_bar

https://www.lexico.com/en/definition/transparent

https://www.lexico.com/en/definition/translucent

Update 08/10/2021

Changing the navigationItem bar buttons after setting the appearance in the way I provided will reset the appearance and you'll have to do it again.

Benjamin
  • 1,832
  • 1
  • 17
  • 27
3

C# / Xamarin Solution

NavigationController.NavigationBar.SetBackgroundImage(new UIImage(), UIBarMetrics.Default);
NavigationController.NavigationBar.ShadowImage = new UIImage();
NavigationController.NavigationBar.Translucent = true;
Mark Moeykens
  • 15,915
  • 6
  • 63
  • 62
3

for Swift 3.0:

override func viewDidLoad() {
    super.viewDidLoad()

    navigationController?.navigationBar.setBackgroundImage(UIImage(), for: .default)
    navigationController?.navigationBar.shadowImage = UIImage()
    navigationController?.navigationBar.isTranslucent = true
}
Wilson
  • 9,006
  • 3
  • 42
  • 46
2

Try the following piece of code:

self.navigationController.navigationBar.translucent = YES;
Thomas W
  • 13,940
  • 4
  • 58
  • 76
Russian
  • 1,296
  • 10
  • 15
1

Another Way That worked for me is to Subclass UINavigationBar And leave the drawRect Method empty !!

@IBDesignable class MONavigationBar: UINavigationBar {


// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
override func drawRect(rect: CGRect) {
    // Drawing code
}}
M.Othman
  • 5,132
  • 3
  • 35
  • 39
1

In Swift 4.2

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

(in viewWillAppear), and then in viewWillDisappear, to undo it, put

self.navigationController?.navigationBar.shadowImage = nil
self.navigationController?.navigationBar.isTranslucent = false
auspicious99
  • 3,902
  • 1
  • 44
  • 58
1

This worked with Swift 5.

// Clear the background image.
navigationController?.navigationBar.setBackgroundImage(UIImage(), for: .default)

// Clear the shadow image.
navigationController?.navigationBar.shadowImage = UIImage()

// Ensure the navigation bar is translucent.
navigationController?.navigationBar.isTranslucent = true
andrewlundy
  • 1,073
  • 15
  • 22
0

Do you mean entirely transparent, or using the translucent-black style seen in the Photos app? The latter you can accomplish by setting its barStyle property to UIBarStyleBlackTranslucent. The former... I'm not sure about. If you want the items on it to still be visible, you might have to do some digging around in the bar's view hierarchy and remove the view containing its background.

Noah Witherspoon
  • 57,021
  • 16
  • 130
  • 131
  • 2
    I mean the former. I tried making a category and overriding the drawRect method of UINavigationBar (invoking CGContextClearRect), but that made it completely black. The items were still visible though. – quano Feb 23 '10 at 03:33
0

This works for Swift 2.0.

navigationController!.navigationBar.setBackgroundImage(UIImage(), forBarMetrics: UIBarMetrics.Default)
navigationController!.navigationBar.shadowImage = UIImage()
navigationController!.navigationBar.translucent = true
Pang
  • 9,564
  • 146
  • 81
  • 122
Chris3643
  • 48
  • 7
0

Check RRViewControllerExtension, which is dedicated on UINavigation bar appearance management.

with RRViewControllerExtension in your project, you just need to override

-(BOOL)prefersNavigationBarTransparent;

in you viewcontroller.

navigation bar tranparent

Roen
  • 116
  • 6
-1
extension UINavigationBar {
var isTransperent: Bool {
        get {
            return false // Just to satisfy property
        }
        set {
            if newValue {
                self.shadowImage = UIImage()
                self.isTranslucent = true
                self.setBackgroundImage(UIImage(), for: .default)
            } else {
                self.shadowImage = UIImage()
                self.isTranslucent = false
                self.setBackgroundImage(nil, for: .default)
            }
        }
    }
}
Dheeraj
  • 11
  • 2