iOS Dev Notes

iOS Development From The Frontlines

Custom UINavigationBar: Two Techniques

with 5 comments

A key component of almost any iPhone or iPad app is the UINavigationBar.  It makes navigating through an app effortless, is intuitive to users, and can even be customized to match almost any style you need.  In this article, we’re going to look at two easy techniques to customize your UINavigationBar.

I’ve created a simple demo app to show the two techniques.  Feel free to follow along with the source code.

Getting Started

First off, let’s talk a bit about how a UINavigationBar is constructed.  Normally you have an XIB (perhaps in your MainWindow.xib file) that contains your Navigation Controller.  Often the default behavior will suffice (though you can always subclass UINavigationController and implement your own behavior if you need to).

In the following example, I have a tab-based layout with three separate Navigation Controllers.  The first one, called “Default”, has its own UINavigationBar and the associated view controller (which, in turn, contains a UINavigationItem).

Once you have the basic setup, build and run your app to make sure things look about right.  You’ll have a plain vanilla blue navigation bar with a text string for a title.  This will form the basis of the next two techniques.

 

Technique 1: Embedded View

In many cases, leaving the actual UINavigationBar alone and instead customizing the UINavigationItem (the title part) is what we’re looking for.  This can be done by embedding a UIView and adding components to that as we see fit.  For instance, in this example, we have a single UIView positioned in the center of the title area, which contains a UILabel and a UIImageView.

This technique is fairly straightforward and can be done entirely within the XIB.  You don’t need to subclass anything, and you can change the appearance of these custom titles easily in the future.  Let’s walk through how to do it.

First, make sure you have a working Navigation Controller setup with a default UINavigationBar as discussed in the Getting Started section.  Once that’s working properly, start by dragging a new UIView onto the Navigation Bar item in your XIB.  As you drag the UIView over the Navigation Bar, it should give you a drop area to place it.  Drop it there.

Next, add elements and customize this view as you like.  I added a UILabel and a UIImageView, carefully aligning them to fit properly.  When you like how it looks, be sure to click on the View and set it’s background color to Clear Color, and (under Drawing) make sure the Opaque checkbox is unchecked.

 

Note that there was a bug in Interface Builder (prior to Xcode 4) which wouldn’t redraw the UINavigationBar with the clear background color in the title UIView until you re-opened the XIB.  If you set the background color to Clear Color and turn off the Opaque checkbox, then try rebuilding your app.  Chances are it will work properly, even if it doesn’t quite look right in IB.

One catch: when you’re using an embedded view as a title, you need to be careful to setup the Back Button property for the Navigation Item the view belongs to.  In this case, I set it to “Simple is good!”.  If you don’t set this, then when you call pushViewController, the next view won’t have a back button.  Normally, the UINavigationController can determine what the back button text should be based on the previous view controller’s title.  But since our title isn’t a UILabel, we need to be explicit about this text.

 

Technique 2: Subclass & Override

The other way of customizing the UINavigationBar is to subclass the UINavigationBar class and override the drawRect: method.  It’s very easy to do, and gives you the most control over how your UINavigationBar will appear.  However, it requires a bit of code.

First, again, make sure you have a basic Navigation Controller with a default UINavigationBar setup in your XIB (as shown in the Getting Started section).  When that’s working, you next want to setup your UINavigationBar subclass.

In Xcode, create a new Objective-C class, and make it inherit from UINavigationBar:

#import <UIKit/UIKit.h>
 
@interface MyCustomNavigationBar : UINavigationBar
 
@end

Next, in the implementation file, override drawRect: (and nothing else!) with whatever you’d like.  In this example, I’m just loading an image  an image as a new background, but you could do just about anything here.

@implementation MyCustomNavigationBar
 
- (void)drawRect:(CGRect)rect {
	UIImage *image = [UIImage imageNamed:@"Custom-Nav-Bar-BG.png"];
	[image drawInRect:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
}
 
@end

Once your custom UINavigationBar is ready to go, you next need to update your XIB to use it instead of the default UINavigationBar class.  Click on the Navigation Bar item in your XIB and set Class to your custom class (in this case, MyCustomNavigationBar).

Rebuild your app and, if everything was done correctly, you should now have a custom UINavigationBar as you set it up in the drawRect: code!  If not, be sure to double check that your custom UINavigationBar is being called and that only the drawRect: method is being overridden.

 

Other Resources

There are a number of additional resources to help you customize your UINavigationBars.  First, be sure to check out the companion source code for this article.

Second, there’s a good discussion at Stack Overflow on the “correct” way to achieve these customizations.  There are other techniques, for instance you could create an Objective-C category and override drawRect: there.  I don’t recommend this approach for several reasons, though the most practical is that you need to be more careful that you are only overriding the UINavigationBars in your app that you actually intend to.  Note this is also known as “method swizzling” which can be quite dangerous if you’re not careful.


Looking to add push notifications to your iOS app? Check out PushLayer, a service from the authors of iOSDevNotes.

Bookmark and Share

Subscribe for updates

Fill out the form below to join my newsletter. I'll also send you a bonus copy of my ebook, "5 Steps To Becoming a Better iOS Developer".

Written by rtwomey

September 29th, 2011 at 3:50 pm

5 Responses to 'Custom UINavigationBar: Two Techniques'

Subscribe to comments with RSS or TrackBack to 'Custom UINavigationBar: Two Techniques'.

  1. Or you can just add a subview to the UINavigationController’s UINavigationBar property. Just don’t forget to remove it when you push / pop another controller.

    Gerusz

    29 Sep 11 at 4:27 pm

  2. Thanks for the information… But, in a UITabbar application with more than 4 tabs, tab #5 and up don’t use the subclassed UINavigationBar and revert to the standard one… This makes the applications look weird as the first for UINavigationBar are customized with a nice background and the others are plain Apple’s one. Solution?

  3. Hi, after ios5 SDK released, the method:
    - (void)drawRect:(CGRect)rect will not be executed, now how to custom UINavigationBar programming

    CaryaLiu

    11 Feb 12 at 2:31 am

  4. How may this be applied to the “More” tab’s navigation bar?

    Brendan

    8 Apr 12 at 10:58 am

  5. [...] http://www.iosdevnotes.com/2011/09/custom-uinavigationbars-techniques/ Tagged: iosquestionsUINavigationBar /* * * CONFIGURATION VARIABLES: EDIT BEFORE PASTING INTO YOUR WEBPAGE * * */ var disqus_shortname = 'dkphp'; // required: replace example with your forum shortname var disqus_identifier = "e7bd9c0623e70ea7155c6d2aca5da020"; var disqus_url = "http://www.dkphp.com/questions-2/creating-a-custom-uinavigationbar-for-ipad-in-ios-5-with-arc.html&quot;; /* * * DON'T EDIT BELOW THIS LINE * * */ (function() { var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true; dsq.src = 'http://&#039; + disqus_shortname + '.disqus.com/embed.js'; (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq); })(); var infolink_pid = 1023613; var infolink_wsid = 2; [...]

Leave a Reply