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
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.
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.
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!
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
.