Custom UINavigationController UIToolbar Background Image
Asked Answered
E

4

16

I have an iPhone application using UINavigationController and would like to customize the elements with custom background images. I was able to do this for the UINavigationController's UINavigationBar pretty easily using Objective-C categories as below:

http://foobarpig.com/iphone/uinavigationbar-with-solid-color-or-image-background.html

I'd like to do the same for the UINavigationController's UIToolbar, but the same approach doesn't seem to work (although I have absolutely no idea why not.) I've looked around and people seem to suggest subclassing UIToolbar, but this isn't possible for the UINavigationController's toolbar, which is a read-only UIToolbar. I want to use the UINavigationController's toolbar instead of just making a subview toolbar because I'm using the slide-in setToolbarHidden animation.

Anyone have any idea if it's possible to apply a background image to this UINavigationController toolbar (most likely by somehow overriding the drawRect method)?

Elfish answered 14/7, 2010 at 8:1 Comment(0)
M
9

You need to subclass instead of creating a category.

I'm not too sure why a category works for UINavigationBar but not UIToolbar, but subclassing works for both of them and I think it's the more standard way of customizing stuff like that.

So to subclass UIToolbar, create a class called MyToolbar (or something similar) and put this in the .h:

#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>

@interface MyToolbar : UIToolbar {}

- (void)drawRect:(CGRect)rect;

@end

And this in the the .m file:

#import "MyToolbar.h"

@implementation MyToolbar

- (void)drawRect:(CGRect)rect {
    backgroundImage = [UIImage imageNamed:@"my-awesome-toolbar-image.png"];
    [backgroundImage drawInRect:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
}

@end

From there you've got to tell the Navigation Controller to use MyToolbar instead of UIToolbar. Easiest way I've found to do that is to select your Navigation Controller in Interface Builder, then in the Attributes Inspector check the 'Shows Toolbar' box. The toolbar should show up in the NavigationController window. Click on it and then in the Identity Inspector change the class to MyToolbar.

Moonfish answered 24/7, 2010 at 3:3 Comment(3)
Great! Thanks. Do you (or anyone else) know of a way to do the last step programmatically? I don't have my navigation controller set up with Interface Builder.Elfish
@Chris, I would also like to know how to override the toolbar programmatically. Thanks!Lamar
Asked/answered in another SO question since I needed to know: https://mcmap.net/q/750008/-custom-uinavigationcontroller-uitoolbar-subclassVentris
G
10

Update:

In iOS 5.0+ you now can use UIAppearance to customize the navigation bar.


Another way to do this is to simply create a Category for your application's UINavigationBar class. This was pretty straightforward to implement:

Interface:

@interface UINavigationBar (TENavigationBar)

- (void) drawRect:(CGRect)rect;

@end

Implementation:

@implementation UINavigationBar (TENavigationBar)

- (void) drawRect:(CGRect)rect
{
    UIImage *image = [UIImage imageNamed:@"navigation_background"];

    [image drawInRect:CGRectMake(0, 
                                 0, 
                                 self.frame.size.width, 
                                 self.frame.size.height)];
}

@end

Then this will be globally applied to all your UINavigationBar's automatically.

Godhead answered 31/10, 2010 at 18:52 Comment(5)
Unfortunately this customizes the nav bar and NOT the toolbar.Sporule
Wow, good point. I totally missed the mark on this one. Still a good solution for nav bar though :)Godhead
I added two files to my code, UINavigationBar.h and UINavigationBar.m and added this code to them. I also tried with file names JHNavigationBar.h/.m. It wasn't automatically applied for me. What am I missing?Shatter
@Shatter are you running iOS 5.0+ only? If so you need to use UIAppearance to customize. This will only work on versions prior to 5.0.Godhead
@Shatter Did you include the interface file wherever it is used? Just adding the file to the project doesn't mean it will get used. Be sure to #import where you wish to use it.Sladen
M
9

You need to subclass instead of creating a category.

I'm not too sure why a category works for UINavigationBar but not UIToolbar, but subclassing works for both of them and I think it's the more standard way of customizing stuff like that.

So to subclass UIToolbar, create a class called MyToolbar (or something similar) and put this in the .h:

#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>

@interface MyToolbar : UIToolbar {}

- (void)drawRect:(CGRect)rect;

@end

And this in the the .m file:

#import "MyToolbar.h"

@implementation MyToolbar

- (void)drawRect:(CGRect)rect {
    backgroundImage = [UIImage imageNamed:@"my-awesome-toolbar-image.png"];
    [backgroundImage drawInRect:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
}

@end

From there you've got to tell the Navigation Controller to use MyToolbar instead of UIToolbar. Easiest way I've found to do that is to select your Navigation Controller in Interface Builder, then in the Attributes Inspector check the 'Shows Toolbar' box. The toolbar should show up in the NavigationController window. Click on it and then in the Identity Inspector change the class to MyToolbar.

Moonfish answered 24/7, 2010 at 3:3 Comment(3)
Great! Thanks. Do you (or anyone else) know of a way to do the last step programmatically? I don't have my navigation controller set up with Interface Builder.Elfish
@Chris, I would also like to know how to override the toolbar programmatically. Thanks!Lamar
Asked/answered in another SO question since I needed to know: https://mcmap.net/q/750008/-custom-uinavigationcontroller-uitoolbar-subclassVentris
A
2

One of the best solutions is creating a category of UINavigationBar and UIToolbar. The next classes gives you a solution for iOS 4.0 and iOS 5.0 compatibility:

The only thing is you need to call the next methods in your viewDidLoad for example:

// Customizacion de navigation bar y toolbar compatible con iOS4 e iOS5
[UINavigationBar iOS5UINavigationBarBackgroundImage];
[UIToolbar iOS5UIToolbarBackgroundImage];    

So, the class Category for iOS 4.0 and iOS 5.0 compatibility for customize BackgroundImage results like follow:

@implementation UINavigationBar (BackgroundImage)
- (void)drawRect:(CGRect)rect 
{    
    UIImage* img = [UIImage imageNamed: @"navigation-bg.png"];
    [img drawInRect: CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];  
    [self setTintColor:UIColorFromRGB(0x5ca666)];      
}
+ (void) iOS5UINavigationBarBackgroundImage
{
    if ([UINavigationBar respondsToSelector: @selector(appearance)])
    {
        [[UINavigationBar appearance] setBackgroundImage: [UIImage imageNamed: @"navigation-bg.png"] forBarMetrics: UIBarMetricsDefault];
        [[UINavigationBar appearance] setTintColor:UIColorFromRGB(0x5ca666)];
    }
}
@end

@implementation UIToolbar (BackgroundImage)
- (void)drawRect:(CGRect)rect 
{
    UIImage *image = [UIImage imageNamed: @"toolbar-bg.png"];
    [image drawInRect:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
    [self setTintColor:UIColorFromRGB(0x5ca666)];
}
+ (void) iOS5UIToolbarBackgroundImage
{
    if ([UIToolbar respondsToSelector: @selector(appearance)])
    {
        [[UIToolbar appearance] setBackgroundImage:[UIImage imageNamed: @"toolbar-bg.png"] forToolbarPosition:UIToolbarPositionAny barMetrics:UIBarMetricsDefault];
        [[UIToolbar appearance] setTintColor:UIColorFromRGB(0x5ca666)];
    }
}
@end

Greets!

Anachronistic answered 8/6, 2012 at 10:28 Comment(0)
R
0

A simple option is to subclass UINavigationBar/UIToolbar and initialize the navigation controller using the method:

- (instancetype)initWithNavigationBarClass:(Class)navigationBarClass toolbarClass:(Class)toolbarClass

However, for simple customizations (as background images, shadows, etc.) I would recommend to use the UIAppearance protocol pattern.

Rundlet answered 21/2, 2013 at 2:47 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.