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:
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
.
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.
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
.
Summary:
So to summarize, the steps you need to take to mimic the UINavigationBar
:
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.
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.
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.