Apple brings a lot of appearance changes in iOS13 and the navigation bar is one of them.
In iOS13 the default appearance of the large title style navigation bar has changed from translucent to transparent.
Nothing changes much in a plain style table view, the navigation bar will show the color of a table view, in this case, white. For grouped style, there is also some offsetting change.
These are not that big of a change, but if your design relies on this colored bar you might need to tweak your design or add some code to going back to old appearance style.
You get this for free (even you might not want it) when you build your app against iOS13 (Xcode11).
Going back to old-style
If you want translucent style back put following code in
let appearance = UINavigationBarAppearance()
UINavigationBar.appearance().scrollEdgeAppearance = appearance
Or if you have colored navigation bar you have to set appearance for both
let coloredAppearance = UINavigationBarAppearance()
coloredAppearance.backgroundColor = .systemPink
coloredAppearance.titleTextAttributes = [.foregroundColor: UIColor.white]
coloredAppearance.largeTitleTextAttributes = [.foregroundColor: UIColor.white]
UINavigationBar.appearance().standardAppearance = coloredAppearance
UINavigationBar.appearance().scrollEdgeAppearance = coloredAppearance
Note that bar color that set with
backgroundColor in iOS13 will result in true color, just like when you set
isTranslucent = false. I still can't figure out how to make it be a translucent color, luckily that I always hate that translucent color. It hard to make it matched the design I get from a designer.
On the left is bar color with
isTranslucent equal to
false, on the right the one with
isTranslucent equal to
true which is the one used in iOS13.
If you want to embrace this change you need to know a new set of API that comes with it, Appearance Customization API.
Appearance Customization API
There is a new class that represents an appearance which encapsulates all customization options for a navigation bar,
UINavigationBarAppearance is a subclass of
UIBarAppearance, which is a base class for other bar appearance,
UITabBarAppearance. I this article we will focus only navigation bar.
You configure this
UINavigationBarAppearance and assign it to new properties in
What are standard/compact/scroll edge appearance?
These 3 appearances represent each presentation style of the navigation bar.
Standard appearance represents a navigation bar in regular height without a large title. This appearance will use to form default for other two,
scrollEdgeAppearance, if you don't specify them.
Compact appearance represents a navigation bar in compact height.
The last one is Scroll edge appearance, based on WWDC session, Modernizing Your UI for iOS 13, this one will be used when navigation associated with a scroll view, but in my test, this one will be used for large title navigation bar even it does not have scroll view.
So to customize your navigation bar what you need to do is create
UINavigationBarAppearance and customize it how you want your bar to be and apply it to any of 3 navigation bar appearances. There are many properties you can set I encourage you to check the UINavigationBarApperance's document to find out what properties you can set.
Here is an example of property and the result you would get.
let standard = UINavigationBarAppearance()
standard.backgroundColor = .systemPink
standard.titlePositionAdjustment = UIOffset(horizontal: -30, vertical: 0)
standard.titleTextAttributes = [.foregroundColor: UIColor.white]
let button = UIBarButtonItemAppearance(style: .plain)
button.normal.titleTextAttributes = [.foregroundColor: UIColor.systemYellow]
standard.buttonAppearance = button
let done = UIBarButtonItemAppearance(style: .done)
done.normal.titleTextAttributes = [.foregroundColor: UIColor.systemGreen]
standard.doneButtonAppearance = done
UINavigationBar.appearance().standardAppearance = standard
One thing I want to highlight here is
UIBarAppearance provided 3 methods to configure appearance.
/// Reset background and shadow properties to their defaults.
open func configureWithDefaultBackground()
/// Reset background and shadow properties to display theme-appropriate opaque colors.
open func configureWithOpaqueBackground()
/// Reset background and shadow properties to be transparent.
open func configureWithTransparentBackground()
The description is quite confusing, but in short, these will set styles based on whether you want your bar to be translucent, opaque, or transparent.
Here is the example of what it looks like for
configureWithOpaqueBackground (I set table view background to pink to make translucent more obvious).
Applying appearance to
UINavigationBar.appearance() or instance of
UINavigationBar will affect every view if you want per view bar appearance you can set
let appearance = navigationController?.navigationBar.standardAppearance.copy()
// Configure appearance
navigationItem.standardAppearance = appearance
And once you've done that, whenever the view controller and navigation item is current, that appearance will be used instead of the navigationBar's base appearance.
This new way of customizing our navigation bar is more flexible and consistent across components. With these changes, I think we can ditch out all the hack we put in all these years to make transparent navigation bar, remove the shadow, etc.
Feel free to follow me on Twitter and ask your questions related to this post. Thanks for reading and see you next time.
Other things I've written
- Data in SwiftUI, Part 2: Views as a function of data SwiftUI iOS Data
- Data in SwiftUI, Part 1: Data SwiftUI iOS Data
- UINavigationBar changes in iOS13 iOS13
- Adopting iOS Dark Mode Xcode iOS Dark Mode
- Modality changes in iOS13 iOS