How to customize UINavigationBar

The navigation bar is one of the most commonly used UIKit visual components, often as part of a UINavigationController. Users are so familiar with the navigation bar, that even single-screen applications, which don’t organize the content in a hierarchy of view controllers that get pushed on and popped off the screen, use it to display the title or buttons at the top of the window.

Because the navigation bar became so ubiquitous, the UIKit API has been offering since iOS5 more and more options to customize its appearance and improve its integration with the overall app design.

This article describes the most common situations where we need to customize the navigation bar to fit specific design requirements. The solutions were tested on iOS8, but most of them should also work on iOS7.

Although UINavigationBar exist and can be used as a standalone component, it’s generally part of a UINavigationController that contains several custom view controllers.
The sample Xcode project for this article uses a navigation controller with a single contained view controller which displays a set of options to explore different visual styles of the navigation bar. It is available for download on GitHub.

Default appearance and behavior

As many other UIKit component, the navigation bar was impacted by the dramatic change in the visual style guidelines introduced by iOS7. Flat design, the preference for transparency to suggest depth, the emphasis on the content rather than the decoration and the consistency between all visual components, are elements that appear clearly in the default aspect and behavior of the navigation bar.

As for the view controllers and other types of bars, the default navigation bar background color is white and the bar is translucent, letting the silhouette of the content which extends behind to be visible.

It is possible to change the default aspect of the navigation bar for the entire application using the UIAppearance proxy. In the AppDelegateM file of the sample project, I set the bar backgroundColor to green, as you can see in the next screenshot taken just after the app launch:

UINavigationBar background color set with UIAppearance proxy

Custom background color

There are two properties of the UINavigationBar class that can be used to change the background color:

  • barTintColor: sets the background color and keeps the translucency
  • backgroundColor: property inherited from UIView, sets the background color and makes the bar opaque

Both properties values are UIColor instances; the alpha channel of the UIColor objects is ignored.

If the properties are simultaneously set, the backgroundColor takes precedence. If you want to reset the background to a translucent color, don’t forget to set the backgroundColor property to nil.

Integration with the status bar

In the recent iOS versions, developers can control the visibility and, in a limited measure, the aspect of the status bar.

Because of the close proximity between the status and the navigation bars, UIKit allows for a tight aspect integration, the status bar being able to inherit some of the visual attributes of the navigation bar.

By default, the background color and translucency of the navigation bar extend to the status bar.

The status bar style applies to the foreground color of the content displayed in the status bar. There are two predefined values: UIStatusBarStyleDefault (dark content on light background) and UIStatusBarStyleLightContent.
Depending on the background color of the navigation bar, which extends behind the status bar, it is possible to change the status bar style to one or the other of the previous values in order to obtain the best contrast.

The applicable status bar style should be returned by the UIViewController method -preferredStatusBarStyle. This method can be overridden in each view controller that needs to customize the status bar appearance.

The status bar visibility and style are managed by the top level view controller, which usually is the navigation controller. If you want to delegate the status bar aspect management to the view controller contained in the navigation controller, you should create a UINavigationController subclass and override the -childViewControllerForStatusBarStyle method to return the topViewController (which is the contained view controller at the top of the navigation stack).

To trigger a change in the style of the status bar, you should also call the -setNeedsStatusBarAppearanceUpdate method on the navigation controller instance (returned by the navigationController property), which invokes the -preferredStatusBarStyle method on the -childViewControllerForStatusBarStyle.

Using background images

It is possible to use a piece of artwork as a background image for the navigation bar. It is set using one of the next methods on the navigation bar instance, depending on the device model, orientation and view controller display mode:

  • setBackgroundImage:forBarMetrics:
  • setBackgroundImage:forBarPosition:barMetrics:

The default height for the background image should be 44 points; in this case, the status bar aspect is totally separated from the navigation bar. If the image is 64 points, the background image will extend behind the status bar.

Tint color and custom navigation bar buttons

The navigation bar buttons are instances of the UIBarButtonItem class. They appear either as simple labels containing the button name, or as images.

To use an image as a bar button item, make sure the title property is set to nil, and set the image property to a UIImage instance initialized from a custom image file, like this:

By default, the image provided to the button is used as a mask, which means the colors contained by the artwork are totally ignored and the shape of the image is filled with the navigation bar tintColor (which is blue, by default).

If you want the actual colors from the artwork, you need to explicitly ask UIKit to use the original aspect of the image file by calling the -imageWithRenderingMode: with the UIImageRenderingModeAlwaysOriginal constant on the UIImage instance:

Conclusion

There are many ways to customize the aspect of the navigation bar and make it an integral part of the app user interface design. I hope this article contributes to the overall understanding of how the navigation bar styling can be implemented.

 

Catalin Rosioru