Customizing the Appearance of UINavigationBar
Remember how the navigation bar of Apple’s Notes application looks on iPhone? It doesn’t look like one of the system provided styles for navigation bar, neither UIBarStyleDefault nor UIBarStyleBlack. And it also looks nice and elegant, doesn’t it?
It, sometimes, would be nice to be able to change the background of the navigation bar and the color of navigation bar buttons as well. There are several ways for changing the background view of the navigation bar, one is inserting a UIImageView as a subview to the UINavigationBar at index 0. But i found this method to be a bit problematic when it comes to adapt the background view when the device interface orientation changes. Instead i create a UINavigationBar category class and override the default behaviour of the -(void)drawLayer:(CALayer *)layer inContext:(CGContextRef)context method. This alters the appearance of all UINavigationBar instances in an application-wide manner and this may be something you don’t want in some cases. However, it is really not so much difficult to use the same technique and change the appearance of UINavigationBars for individual instances. What we’ve done here may also be useful in the case you want to implement a visual theming system for your application. By dynamically changing the images we use as background, it’s possible to make UINavigationBars look different with different themes your application provides.
Let’s have a look at what’s going on in UINavigationBar(CustomBackground) category class:
The two methods +(UIImage *)bgImagePortrait and +(UIImage *)bgImageLandscape provide background images for portrait and landscape interface orientations. File extensions are omitted in image names to tell iOS that HD versions of images are available. Please note that images are lazy-loaded and cached by these methods, and once they are created they will remain in the memory until the application exits. If this is something you don’t want, you can easily modify that part.
Inside the -(void)drawLayer:(CALayer *)layer inContext:(CGContextRef)context method, we first determine the interface orientation of the device by checking the width of the current UINavigationBar instance and we choose one of the two images accordingly. Then we draw the image in context. And finally, the -(void)applyCustomTintColor method is what we use in order to change the color of UINavigationBar buttons. This method should be called for every UINavigationController instance we create to modify its UINavigationBar:
#import "UINavigationBar+CustomBackground.h" ... UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:aViewController]; [navigationController.navigationBar applyCustomTintColor]; ...
You can download the complete source code of the demo app on github as an Xcode project:
And here is the Git read-only url, if you’d like to clone it to your local repo:
Some screenshots from the demo app running on the iPhone simulator: