8
votes

I have a navbar that is set to translucent. I do not want to change this. I set the bar tint color on the navbar and it looks great. However the color I set is not the 'true' color that is displayed since I have translucent set to 'YES'.

I have another view that has a background. I would like to set the background color of that view to the same color as the navbar. However jsut setting the colors the same does not work. Since the navbar is translucent.

I would like my view's background to have the same translucency so that my colors match.

To state again I do not want to change the navbar's translucency or color. I want to create a view that has the same color and translucency as the navbar. However in iOS you just set translucent to 'YES', I am not sure what effect (ie maybe what alpha) that really sets. Is there a formula I can apply to my views background to match the navbar?

1
I'm looking at this same problem now and am using the layer inspector to look at the navigation bar.Moshe
See my edits - lots of new info...Moshe

1 Answers

15
votes

I'm looking at this same problem now and am using the layer inspector to look at the navigation bar.

As it turns out, the UINavigationBar actually has two colored layers in it. One of them is based on your color, and one is a semitransparent near-white layer.

Have a look at this screenshot:

enter image description here

There's two layers.

The top layer (marked as A) has my color, in this case, a blue defined by UIColor(red: 0.13, green: 0.20, blue: 0.62, alpha: 1.00). This layer is set to an opacity of .85.

Beneath that, there's a second layer, marked as B, with a near-white with a background color defined as UIColor(white: 0.97, alpha: 0.5).

I haven't worked out how to imitate this in my library that I'm developing, but this screenshot has given me something to work with. I also am not sure how to mimic the borders, but this should be a great starting point.

Edit: As I said, here's some more info.

The Bottom Border:

I spent some more time on this yesterday, and I found a few interesting things: The bottom border of a UINavigationBar is actually a half-pixel tall UIImageView. It has no image, but it has a background color that's defined as UIColor(red: 0.0, green: 0.0, blue:0.0, alpha: 0.3).

I wasn't sure why they used an empty image view instead of a UIView but I have a theory now. When I set the border on my FilterBar view, I noticed that my color, defined exactly the same way, was not the same shade as the one in the UINavigationBar.

First, I realized that I was setting the border and the near-white color on the FilterBar itself, and the barTintColor was in a second layer. The near-white was bleeding into the border, so I added another layer for the white.

My border was still the wrong color. So, I dug deeper. I started printing the view objects into the debugger and I noticed that my border color was defined in the CGColorSpaceGray color space, and the UIImageView was defined in CGColorSpaceRGB.

enter image description here

To solve this problem, I manually created the color space I needed and then the transparent black color. On the device, it works perfectly, but on the simulator it's still a little off.

Here's what I used to make that color, in Swift:

    let space : CGColorSpace = CGColorSpaceCreateDeviceRGB()
    let color : CGColor = CGColorCreate(space, [0.0, 0.0, 0.0, 0.3])

Setting the layer's borderColor to color and borderWidth to 0.5, I see a near identical view to the native navigation bar. I think this is why the UINavigationBar uses a UIImageView for the border. Although I haven't tested it yet, I suspect that it's there for the color space.

enter image description here

Layers:

I noted earlier that UINavigationBar is comprised of three layers. Well, actually, it's the private class _UINavigationBarBackground that's comprised of several layers, and that backdrop is only present if the navigation bar has translucency enabled.

If translucency is disabled, the UINavigationBar will apply the color to itself and hide the backdrop hierarchy. I've mimicked that behavior in FilterBar.

enter image description here

Summary:

So to summarize, the steps you need to take to mimic the UINavigationBar:

  1. For color, you want to add two layers to your view. The topmost layer takes your barTintColor, and has an 85% opacity. For an opaque version, remove the extra layers and set the color directly.

  2. To match the border, use a black color with 30% opacity, make sure you have the correct color space and make sure that your backdrop layers don't overlap, or they'll mess with your border.

  3. If you really want to match the behavior of the UINavigationBar, make your backdrop view stretch upward, beneath the status bar.

You can see my implementation in FilterBar on GitHub.