71

How can I get the right coloring for my translucent navigation bars in iOS 7? The navigation bar just adjusts the given color to a much brighter one. Changing brightness or saturation of the color also doesn´t deliver the right result.

Anyone having the same trouble? It seems to work somehow, looking at Facebook: they´re having their colors and translucent navigation bars.

Edit: Just to make it clear: I need the Bar to be translucent, not transparent (with some alpha), not solid! http://en.wikipedia.org/wiki/Transparency_and_translucency

Edit: Now posted to Apple BugReporter

stk
  • 6,311
  • 11
  • 42
  • 58
  • 1
    I think that with iOS 7.0.3 this is not needed anymore as it is now setting the right colour. You can play with alpha however and the calculators posted here can help you with that. – Fábio Oliveira Oct 25 '13 at 09:53

20 Answers20

81

The bar will adjust your color values.

Preferred method, for RGB >= 40 only, will give the most blurring

You can use this calculator and put in what you want the color to be when rendered on screen, it will tell you what to set the color of the barTintColor so when Apple adjusts it, it will show as intended

https://www.transpire.com/insights/blog/bar-color-calculator/

Edit: Note that these calculations are for a white background, and for lighter colours (rgb over 40, if you need darker, you will need to add a background layer like others have mentioned - although that will reduce the bar's blur)

In depth guide: https://www.transpire.com/insights/blog/custom-ui-navigationbar-colors-ios7/

Snippet:

@interface UnderlayNavigationBar : UINavigationBar

@end

.

@interface UnderlayNavigationBar ()
{
    UIView* _underlayView;
}

- (UIView*) underlayView;

@end

@implementation UnderlayNavigationBar

- (void) didAddSubview:(UIView *)subview
{
    [super didAddSubview:subview];

    if(subview != _underlayView)
    {
        UIView* underlayView = self.underlayView;
        [underlayView removeFromSuperview];
        [self insertSubview:underlayView atIndex:1];
    }
}

- (UIView*) underlayView
{
    if(_underlayView == nil)
    {
        const CGFloat statusBarHeight = 20;    //  Make this dynamic in your own code...
        const CGSize selfSize = self.frame.size;

        _underlayView = [[UIView alloc] initWithFrame:CGRectMake(0, -statusBarHeight, selfSize.width, selfSize.height + statusBarHeight)];
        [_underlayView setAutoresizingMask:(UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight)];
        [_underlayView setBackgroundColor:[UIColor colorWithRed:0.0f green:0.34f blue:0.62f alpha:1.0f]];
        [_underlayView setAlpha:0.36f];
        [_underlayView setUserInteractionEnabled:NO];
    }

    return _underlayView;
}

@end

.

UIViewController* rootViewController = ...;
UINavigationController* navigationController = [[UINavigationController alloc] initWithNavigationBarClass:[UnderlayNavigationBar class] toolbarClass:nil];
[navigationController.navigationBar setBarTintColor:[UIColor colorWithRed:0.0f green:0.0f blue:90.0f/255.0f alpha:1]];
[navigationController setViewControllers:@[rootViewController]];
Cœur
  • 37,241
  • 25
  • 195
  • 267
SomeGuy
  • 9,670
  • 3
  • 32
  • 35
  • 2
    Thanks and +1 for the calculator! Basically what it says is: You can´t have colors that are 'darker' than 102 in any value of RGB. This is bad, because my management won´t allow me to choose any other color than the companies' (which is RGB 181,27,32), just because Apple dictates so. There´s got to be another way, because Facebook is also much darker, it has RGB 65,95,156 in the current version of their app. – stk Sep 30 '13 at 09:19
  • 1
    You can still do darker colours, the downside is you need to add an underlay view to darken things up, which means the darker you go the weaker the blur will get. I've managed to recreate the Facebook blur of 65,96,156 with the following code. I did this with trial and error, the aim is to get the alpha of colourView to be as low as possible. http://img707.imageshack.us/img707/3151/482w.png – SomeGuy Oct 01 '13 at 00:38
  • 1
    I still had the darker burn across the title, so to fix that, I added ` [navigationBar setBackgroundColor:[[UIColor alloc] initWithWhite:0.0f alpha:0.0f]];`. Seemed to work. – dclowd9901 Oct 06 '13 at 19:54
  • 1
    You may wanna add autoresizing to support orientation changes: `colourView.autoresizingMask = UIViewAutoresizingFlexibleHeight|UIViewAutoresizingFlexibleWidth;` – Maciej Swic Oct 09 '13 at 13:55
  • 1
    Although this wan't really meant to be a guide for simply setting it up, I've added some autoresizing masks and made it a bit more dynamic for the people that copy and paste without reading it. – SomeGuy Oct 09 '13 at 23:38
  • 1
    @SomeGuy Also, I'm experiencing some strange results in iOS 7. If the colorView is inserted at index 1, it looks like it appears over the title and back button text if you push another view onto the navigation stack. If you put it on index 0 however everything works as expected. Thoughts? – Maciej Swic Oct 10 '13 at 10:31
  • 1
    @Maciej Swic I've just added some fixes for index positioning, as well as a link to my more in depth blog post on using darker colors in conjunction with a blur on the navigation bar in iOS7 – SomeGuy Oct 10 '13 at 13:32
  • 4
    There is an document from apple describe how to "Matching a Bar Tint Color To Your Corporate or Brand Color" https://developer.apple.com/library/ios/qa/qa1808/_index.html – Amio Sep 23 '15 at 09:05
13

You simply need to change translucent property

navigationBar.translucent = NO;

It is effectively the same as removing/making transparent subviews/sublayers of the navigation bar.

malex
  • 9,874
  • 3
  • 56
  • 77
4

I've improved code from Achieving bright, vivid colors for an iOS 7 translucent UINavigationBar in my fork: https://github.com/allenhsu/CRNavigationController

With my modification, the result color on screen (picked on white background) will be exactly the same value passed into setBarTintColor. I think it's an amazing solution.

Community
  • 1
  • 1
Allen Hsu
  • 3,515
  • 3
  • 25
  • 38
3

I know this answer is a little late, but if you're using Interface Builder, you might be getting the wrong color when using a hex value because Interface Builder is set to use the wrong color space. In Xcode 6.4, you can press the little gear in the top right of the color picker dialog to pick which color space you're using:

enter image description here

Mine was set to sRGB IEC6196-2.1, when I actually should have been using Generic RGB.

Elethier
  • 85
  • 7
2

If your color isn't exceptionally vivid, you can calculate the equivalent color w/ alpha. This works well in iOS 7.0.3+; prior to 7.0.3 it automatically applied a 0.5 alpha.

This code assumes that your input color is RGB and is opaque, and that your background color is white:

- (UIColor *) colorByInterpolatingForBarTintWithMinimumAlpha: (CGFloat) alpha
{
    NSAssert(self.canProvideRGBComponents, @"Self must be a RGB color to use arithmatic operations");
    NSAssert(self.alpha == 1, @"Self must be an opaque RGB color");

    CGFloat r, g, b, a;
    if (![self getRed:&r green:&g blue:&b alpha:&a]) return nil;

    CGFloat r2,g2,b2,a2;
    r2 = g2 = b2 = a2 = 1;

    CGFloat red,green,blue;

    alpha -= 0.01;
    do {
        alpha += 0.01;
        red = (r - r2 + r2 * alpha) / alpha;
        green = (g - g2 + g2 * alpha) / alpha;
        blue = (b - b2 + b2 * alpha) / alpha;
    } while (alpha < 1 && (red < 0 || green < 0 || blue < 0 || red > 1 || green > 1 || blue > 1));

    UIColor *new = [UIColor colorWithRed:red green:green blue:blue alpha:alpha];
    return new;
}

If anyone has a more elegant way of calculating the alpha (I'm cringing at that do-while loop) I'd love to see it: https://gist.github.com/sgtsquiggs/7206385

Matthew Crenshaw
  • 322
  • 1
  • 4
  • 14
2

Just use this simple barTintColor Calculator:

http://htmlpreview.github.io/?https://github.com/tparry/Miscellaneous/blob/master/UINavigationBar_UIColor_calculator.html

enter image description here

Damien Romito
  • 9,801
  • 13
  • 66
  • 84
2

Here is another way to get right color of translucent navigation bar in iOS 7.x and later. For some colors it's possible to find the optimal bar tint color that makes translucent bar to appear with color that matches the desired one.

For example, for Facebook color that is rgb: 65,96,156 or #41609c the optimal color is #21458c. The following code set all navigation bars in the app to be of Facebook color with native cocoa-touch API only:

UIColor* barColor = [UIColor colorWithRed:0.129995 green:0.273324 blue:0.549711 alpha:1.0]; // #21458c to make bars actual color match the #41609c color.
[[UINavigationBar appearance] setBarTintColor:barColor];

The only limitation of the method is that optimized color can't be found for every possible color. Usually this is not possible for dark colors.

I made an BarTintColorOptimizer utility that should be run on the device to search for optimized bar color for any color you enter.

IvanRublev
  • 784
  • 9
  • 10
  • BarTintColorOptimizer is great! – Gamec Feb 01 '18 at 11:27
  • 1
    Almost five years later, and this underrated answer is still the only "correct" solution (in so far as any solution for this problem is "correct"). It's baffling that Apple's advice on this amounts to "figure it out yourself". Thanks for writing BarTintColorOptimizer! – sizzle beam Sep 29 '20 at 08:56
1

I suppose you have read all the comments above. If you want to get the custom background & translucency you should override the navigationbar class and implement your own layoutsubviews method. Simple add additional subview here. IMPORTANT: you should add it just above the background subview of the NavigationBar. It will hide your header or buttons if you just put it above the all subviews.

Also, check out this question

Community
  • 1
  • 1
gleb.kudr
  • 1,518
  • 12
  • 16
  • 1
    avishic delivered exactly this approach 1,5 days before your answer. Correct me if I´m wrong... – stk Sep 30 '13 at 09:22
  • 1
    Not exactly the same. He is moving newSubview behind all subviews of the navigation bar. But you should place it just above the original nav bar background which remains to be the last subview. – gleb.kudr Sep 30 '13 at 16:17
1

Simple/fast solution that worked for me. Just set the bar tint in the storyboard rather than the background.

First select your Navigation Bar in your Navigation Controller
Navigation Bar

And then click the attributes inspector on the right and then set the Bar Tint
Bar tint

You can select a pre-defined color or click on the color to set it to something else.
enter image description here

Markymark
  • 2,804
  • 1
  • 32
  • 37
0

To make tint color look darker you can change the backgroundColor of the navigation bar:

UIColor *color1 = [UIColor colorWithRed:55.0f/256.0f green:0.0f blue:1.0f alpha:1.0f];
[navBar setBarStyle:UIBarStyleBlackTranslucent];
[navBar setBarTintColor:color1];
UIColor *color2 = [UIColor colorWithWhite:0 alpha:0.3];
[navBar setBackgroundColor:color2];

Try playing around with color1 and color2 to achieve the result that fits to you. Anything else would be fighting the framework.

Eugene Dudnyk
  • 5,553
  • 1
  • 23
  • 48
  • 1
    This doesn't work as it doesn't cover the area under the status bar, and also shows a gradient close to the bottom of the nav bar. – Ian Hoar Oct 03 '13 at 23:16
0
navBar.barTintColor = [UIColor orangeColor];
navBar.translucent = YES;
UIColor *backgroundLayerColor = [[UIColor redColor] colorWithAlphaComponent:0.7f];
static CGFloat kStatusBarHeight = 20;

CALayer *navBackgroundLayer = [CALayer layer];
navBackgroundLayer.backgroundColor = [backgroundLayerColor CGColor];
navBackgroundLayer.frame = CGRectMake(0, -kStatusBarHeight, navBar.frame.size.width,
        kStatusBarHeight + navBar.frame.size.height);
[navBar.layer addSublayer:navBackgroundLayer];
// move the layer behind the navBar
navBackgroundLayer.zPosition = -1;

Note you'll still need to muck with the the barTintColor and the backgroundLayerColor to get the exact color you want. Also, of course the colors depends on your content view's background color (e.g. white).

bobics
  • 2,301
  • 2
  • 23
  • 25
0

I've extented UINavigationController,
on its viewDidLoad, i've added a background with the same color of the tint.

Also, i've set the background frame to cover the status bar area:

    self.navigationBar.barTintColor = navBackgroundColor;
    CGRect bgFrame = self.navigationBar.bounds;
    bgFrame.origin.y -= 20.0;
    bgFrame.size.height += 20.0;
    UIView *backgroundView = [[UIView alloc] initWithFrame:bgFrame];
    backgroundView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
    backgroundView.backgroundColor = navBackgroundColor;
    backgroundView.alpha = 0.6;
    [self.navigationBar addSubview:backgroundView];
    [self.navigationBar sendSubviewToBack:backgroundView];

On my case alpha 0.6 got the job done, but you can play with it.

Avishay Cohen
  • 2,418
  • 1
  • 22
  • 40
  • 1
    Back button in pushed view controller stops working for me with this code, although Done works fine – Nik Sep 25 '13 at 10:56
  • 1
    Solved this issue using technique described in http://stackoverflow.com/questions/3046813/how-can-i-click-a-button-behind-a-transparent-uiview – Nik Sep 25 '13 at 11:08
  • 1
    You should add you subview just above the background view of the NavigationBar. And the back buttons will be fine. – gleb.kudr Sep 25 '13 at 19:23
0

If you're using swift 2.0 you can use this, this will remove the blur and have the color show properly.

UINavigationBar.appearance().translucent = false
icekomo
  • 9,328
  • 7
  • 31
  • 59
0

From comparing my before an after colors I found there was a drop of 21% in saturation while Hue and Brightness remained the same.

By adding the 21% back on I was able to improve the color matching significantly. Unfortunately our color had a saturation above 80 to start with so pushing it above 100% had diminishing returns and didn't match perfectly but it got much closer.

For colors with saturation below 80 it should do even better.

For info on how to adjust saturation of your color How can I modify a UIColor's hue, brightness and saturation?

Community
  • 1
  • 1
SuperGuyAbe
  • 525
  • 1
  • 5
  • 5
0

You can run the application in the simulator and take the color of the navigation bar using the Eyedropper tool.

enter image description here

Vladimir
  • 1,053
  • 10
  • 8
0

i've looked a lot around and none of these has actually worked for me, the solution is as the following:

1- Set your navigation barTintColor (background).

2- Run the simulator and open your app, in your mac open Digital Color Meter and select the drop down to "Display in Generic RGB".

enter image description here

3- Use this tool to pick the navigation color that you will set for your view.

4- Go to storyboard and then select background color and make sure its on RGB Sliders, and put the color in here, you will get the exact same color of the navigation bar.

enter image description here

Note: it doesn't matter if isTranslucent is on or off.

Hope this helps you out.

AaoIi
  • 8,288
  • 6
  • 45
  • 87
-1

This should work:

UIColor *barColour = [UIColor colorWithRed:0.13f green:0.14f blue:0.15f alpha:1.00f];

UIView *colourView = [[UIView alloc] initWithFrame:CGRectMake(0.f, -20.f, 320.f, 64.f)];
colourView.opaque = NO;
colourView.alpha = .7f;
colourView.backgroundColor = barColour;

self.navigationBar.barTintColor = barColour;

[self.navigationBar.layer insertSublayer:colourView.layer atIndex:1];

Taken from here

Scott Berrevoets
  • 16,921
  • 6
  • 59
  • 80
  • 1
    This only works, if you have no title set in your NavigationBar. If you have a title set, it is dimmed out by the colorView. – stk Sep 20 '13 at 17:46
  • 1
    This code leaves navigation bar's layer correspondent for z-order and frame further adjustments to the layer you created. Basically bad approach. To go this way you need to create the navigation bar subclass to deal properly with subviews on your navigation bar by overriding its layoutSubviews method. – Eugene Dudnyk Sep 24 '13 at 07:59
-2

This works for me:

CALayer *layer = [CALayer layer];
layer.frame = CGRectMake(0, -20,navigationBar.frame.size.width,navigationBar.frame.size.height + 20);
layer.backgroundColor = [[UIColor blueColor] colorWithAlphaComponent:0.75].CGColor;
layer.zPosition = -5;
[navigationBar.layer addSublayer:layer];
user1007895
  • 3,925
  • 11
  • 41
  • 63
  • 1
    Have you read some of the other answers? The 'adding-layer-to-navbar'-approach has been posted at least twice before your answer. – stk Sep 30 '13 at 09:25
-4

This happens because the navigationBar.translucent == YES. Set this property to NO and it will be the correct color. However, I have not found out how to apply this translucent setting to all navigation bars without calling it explicitly on each. The status bar also stays the same color as the navigation bar this way.

user1529956
  • 735
  • 2
  • 10
  • 24
  • 1
    Sorry, but I clearly stated that I need the bar to be translucent. – stk Sep 23 '13 at 09:07
  • 1
    Facebooks is not translucent either. What makes you say it is? If you want the bar is be translucent, there's no way to get the true color since it'll have an alpha < 0 – user1529956 Sep 23 '13 at 15:33
  • 1
    Just scroll an image under the NavigationBar and you will recognize it´s translucent. – stk Sep 23 '13 at 18:57
  • 1
    Facebook bar is translucent. Getting tired of people with iPhone 4 telling everyone Facebook bar is not, when it clearly is. – Léo Natan Sep 23 '13 at 21:18
  • 1
    I have the iPhone 5 and it is not translucent on mine. Not sure why it differs. – user1529956 Sep 23 '13 at 23:04
  • 1
    Sorry, I meant to say alpha < 1 in my other post. That's like setting any color alpha (anywhere) to < 1 then saying, "Why is the color not the same as when when the alpha = 1." – user1529956 Sep 23 '13 at 23:12
  • 1
    Oh my mistake, it apparently is translucent but it wasn't noticeable. – user1529956 Sep 23 '13 at 23:15
-4

Try rendering corresponding background image for your navigation bar. That worked for my test application.

UIGraphicsBeginImageContext(CGSizeMake(1, 1));
CGContextRef context = UIGraphicsGetCurrentContext();
[[UIColor colorWithRed:55.0f/256.0f green:0.0f blue:1.0f alpha:0.5f] set];
CGContextFillRect(context, CGRectMake(0, 0, 1, 1));

UIImage *navBarBackgroundImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

[[UINavigationBar appearance] setBackgroundImage:navBarBackgroundImage forBarMetrics:UIBarMetricsDefault];
[[UINavigationBar appearance] setBackgroundImage:navBarBackgroundImage forBarMetrics:UIBarMetricsLandscapePhone];
Eugene Dudnyk
  • 5,553
  • 1
  • 23
  • 48
  • 1
    That results in a transparent, but not translucent NavigationBar. http://en.wikipedia.org/wiki/Transparency_and_translucency – stk Sep 23 '13 at 19:03
  • 1
    Okay, then fill apple bug report and ask designers to provide proper background image if system-provided translucency is not what you want. – Eugene Dudnyk Sep 24 '13 at 07:52
  • 1
    Sorry, but I´m only getting transparency with your approach. There´s no blurry effect whatsoever. Translucency (in Apple-speak) inherits the blurry effect like the NavigationBar etc. has when you set navigationBar.translucent = YES; – stk Sep 24 '13 at 10:15
  • 1
    Hey man, you're cruel making -1 to my post. It is fully correct, and transparency is the partial case of the translucency. If you are bored with useless answers, this community is not for you. – Eugene Dudnyk Sep 30 '13 at 11:47