Adding any kinds of UI elements into a UINavigationBar

In iCab Mobile and many other iPhone apps you can see a toolbar with buttons, text fields and other UI elements at the top of the screen. And this toolbar looks like a UINavigationBar object. But if you try to add UI elements into a UINavigationBar object in Interface Builder, you’ll notice that you can’t add all UI elements in any location within the UINavigationBar. More concrete: you can add up to three elements in concrete spots (left, middle, right), and only certain UI elements. A UINavigationBar object is meant to be used for navigation purposes and therefore is usually automatically populated by a UINavigationController. And the UINavigationController only uses the three spots (left to go back to the previous navigation level, the center area to display the title and the right to add an “edit” button for example).

So how are iCab Mobile and other apps able to populate a UINavigationBar object with any UI elements in other than the three available spots?

First of all, not everything which looks like a UINavigationBar is a UINavigationBar. Up to iCab Mobile 1.7 the toolbar at the top of the screen is not a UINavigationBar object, it’s a UIImageView object with an image that looks like a UINavigationBar would look like. But since iCab Mobile 2.0 it will be a UINavigationBar. iCab Mobile 2.0 will allow to customize the colors of the toolbars, and unlike images, the UINavigationBar object can have any color.

But even for UIImageView objects, you can’t add any subviews in Interface Builder. So the main question is the same: how to add any available UI elements in any location as subview of these objects (it doesn’t matter if these objects are UIImageView or UINavigationBar objects)?

The answer is simple: you have to do this programatically. UIImageView and UINavigationBar are both subclasses of UIView. And UIView objects can have subviews. You only need to call the method addSubview: to add a subview. When using UINavigationBar as the root for our toolbar, we only have to make sure that it is not managed by a UINavigationController. But because we need to create all the objects programmatically, this isn’t a problem at all.

One place to create the toolbar can be the viewDidLoad method of the UIViewController which serves as the controller for the view that holds the toolbar. The following code is an example how this would look like. All the code fragments should go into the viewDidLoad method, I’ve split the code into fragments only because it’s easier to explain what I’m doing this way.

- (void)viewDidLoad
  [super viewDidLoad];

  CGFloat width = self.view.frame.size.width;

Here we first get the width of the view of our UIViewController. It is used to calculate the widths of all of the toolbar elements.

  UINavigationBar *navBar = [[UINavigationBar alloc] initWithFrame:
  navBar.autoresizingMask = UIViewAutoresizingFlexibleWidth;
  [self.view addSubview:navBar];
  [navBar release];

This fragment creates the UINavigationBar element and we add it as subview to the view object of our UIViewController. If the application should support the autorotation feature, we have to make sure that the width is flexible and set the autoresizing mask accordingly.

  UILabel *label = [[UILabel alloc] initWithFrame:
  label.autoresizingMask = UIViewAutoresizingFlexibleWidth;
  label.text = @"some text for the title...";
  label.backgroundColor = [UIColor clearColor];
  label.font = [UIFont systemFontOfSize:12];
  label.textAlignment = UITextAlignmentCenter;
  [navBar addSubview:label];
  [label release];

Then we create the title line of our toolbar. We use a UILabel element. The width must be flexible as well when the autorotation feature is supported. The label is added as a subview of the UINavigationBar object so that there is a small margin at the top, left and right side. It is important to set the background color to “clearColor” to make the background completely transparent. The default background color would be white.

  UITextField *textField = [[UITextField alloc] initWithFrame:
  textField.autoresizingMask = UIViewAutoresizingFlexibleWidth;
  textField.borderStyle = UITextBorderStyleRoundedRect;
  textField.font = [UIFont systemFontOfSize:17];
  [navBar addSubview:textField];
  [textField release];

This fragment will add a text field to enter some text into the toolbar. This is similar to what we’ve done to add the label.

  UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
  [button setFrame:CGRectMake(width-60,19,50,26)];
  [button setTitle:@"Go" forState:UIControlStateNormal];
  button.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin;
  [navBar addSubview:button];

And finally we’ve added a button to the toolbar. Nothing special here. This time the autoresizing mask is set to have a flexible left margin, because the button should always have the same width. It only should be placed on the right side of the toolbar, so the right margin must be fixed, while the left must be flexible.

This is more or less all you need to do to add UI elements in UINavigationBar objects. Of course you also need to set the delegates for some of the UI elements in order to process clicks on the button or text field editing.

This is how the toolbar from above will look like:

20 thoughts on “Adding any kinds of UI elements into a UINavigationBar

  1. That’s not a lot of code????

    How would we do something this simple… all in IB?
    4 buttons… but looks like they are on navigation bar?

  2. If you don’t need a NavigationBar’s back button, why not just do it all in IB with a toolbar as your base? Toolbars don’t just have to go on the bottom of the view.

  3. Yes, since OS 3.2 you can also place the toolbars at the top of the screen. But at the time I wrote this article, OS 3.2 was not available and it was not possible to place a UIToolbar at the top of three screen without some visual glitches.

  4. Hi Alexander

    I am trying to create a uinavigation bar which is quite similar to the one we find in safari (iPad). The issue is that I am not able to add uibarbuttonitems to the navigation bar. The navigation bar would be more than 44 pixel.

    Can you please explain, how you added those uibarbuttonitems (bookmarks,etc) to the navigationbar in iCab?

    Thanks very much.

  5. @Kartik Thapar

    In iCab Mobile the toolbar is just a normal UIView with a background image. And the buttons are standard UIButtons.

    But even if you’re using a navigation toolbar (which is also just a UIView), you have to add normal buttons (as subviews) instead of UIBarButtonItems if you need more than just two buttons in the toolbar. A navigation toolbar accepts only two UIBarButtonItems at certain locations. And because a UIBarButtonItem is not a UIView, you can’t add them as subviews as normal UIViews.

  6. Thanks Alexander. Much help.

    Would it be possible for you to pass me those button images? I am looking out for the search button, actions button and organise button. I am not good at photoshop, so I cannot make them myself.

    Thanks for your help.

  7. How do you disable buttons that you’ve added to the uinavigation bar, esp if you do it this way? Thanks

  8. @AD
    Just use the standard methods for the buttons to disable them. UIButton objects (or UIControl objects) do have properties like “selected”, “enabled”, “highlighted”. So there’s nothing special here.

  9. Thanks Alexander.
    I wonder how did you show the progress in the UITextField you put on the navigationBar? I used a private API [UITextField setProgress:(float)value], but the result is very strange.

  10. @Allen
    You don’t need a private API for this. All you need to do is to place a UIView with a semi-transparent background color on top of the URL field and resize this view based on the current progress value. And if you make sure that the user-interaction property for this UIView is switched off, all taps on this view will go directly to the URL field which is located below the progress view.

  11. Hi,
    Good explanation!
    If I want to refer this navBar instance, somewhere else in the code and change its leftBarButtonItem, how do I do it? I only succeed when I defined the navBar again and add it again to self.view. I assume there is a better way to do it.

    Thanks a lot,

  12. @Miri
    When using a UINavigationController, you can set the left and right buttons only under certain conditions, because the controller really controls almost everything at all times. This means you can usually only use the default behavior of the UINavigationController.
    When using a Navigation toolbar without a navigation controller you have much more freedom.

  13. Hi Alexander,

    That’s what I did – I used a Navigation toolbar without a navigation controller. I added a Navigation toolbar programmatically in viewDidLoad. Then, in another function, I wanted to change its leftBarButtonItem and I was able to do it only when I added again the Navigation toolbar.


  14. @Miri
    I’m not sure what exactly you’re doing.Maybe you should create a small demo project and send it to me, so I can see what you’ve done.

  15. On iOS 8 (I think works on iOS 7 also) you can use a UIToolbar. you put it at the top, and then can set the delegate and use a method to say it is top attached, then you can use the items property and it works great! Im doing this in my app which also supports rearranging of items. The only downside of this still is any custom view bar item (anything not just a image) you have to calculate the width for, so flexible spacing sucks. also I see in iCab you have long tap and hold actions, which UIBarButtonItem cannot do unless it is a custom view.

  16. func buttonTouched(sender:UIButton!)

    for subView in self.navigationBar.subviews {
    if subView.isKindOfClass(NSClassFromString(“UINavigationButton”)) {

    the subView is my UIview(well it’s an animation). This works but i can’t seem to manage what side of the navigation bar it presents. By default it placing the animation on the left side. I need it on the right. Any way to implement it as a rightbarItem?

  17. @Andy McDonald
    In general you can create UIBarButtonItems with custom views and attach these to the rightBarButtomItem (or if multiple views/buttons needs to be added, attach a whole array to „rightBarButtomItems“).
    But in any case if you rely on the left/rightBarButtomItem properties, you have to set these properties on the view controller that is currently the top on within the navigation controller. Directly manipulation the navigation toolbar won’t work, because the navigation controller will automatically replace items depending on the users actions.

Leave a Reply

Your email address will not be published. Required fields are marked *