I would like to set an image as UINavigationController background but most solutions I found apply background in navigation bar for all views in the app. Can you give some code that may help ?
Thx for helping,
Stephane
I would like to set an image as UINavigationController background but most solutions I found apply background in navigation bar for all views in the app. Can you give some code that may help ?
Thx for helping,
Stephane
Here's a quick and dirty way that I use in one of my projects (I have no need to support landscape orientation). I implemented it with a category to UINavigationBar
with method swizzling. Works on iOS 4 and 5 (I didn’t try it on iOS 3).
UINavigationBar+SYCustomBackground.h
#import <UIKit/UIKit.h>
@interface UINavigationBar (SYCustomBackground)
@property (nonatomic,retain) UIImage *sy_customBackgroundImage;
@end
UINavigationBar+SYCustomBackground.m
#import "UINavigationBar+SYCustomBackground.h"
#import <objc/runtime.h>
@implementation UINavigationBar (SYCustomBackground)
static char BACKGROUND_IMAGE_KEY;
static BOOL drawRectsSwizzled = NO;
// Swizzles drawRect: and sy_drawRect:
- (void)swizzleDrawRectIfNecessary
{
if (!drawRectsSwizzled) {
Method origMethod = class_getInstanceMethod([self class], @selector(drawRect:));
Method myMethod = class_getInstanceMethod([self class], @selector(sy_drawRect:));
method_exchangeImplementations(origMethod, myMethod);
drawRectsSwizzled = YES;
}
}
- (void)setSy_customBackgroundImage:(UIImage *)image
{
// iOS 5
if ([self respondsToSelector:@selector(setBackgroundImage:forBarMetrics:)]) {
[self setBackgroundImage:image forBarMetrics:UIBarMetricsDefault];
}
// iOS < 5
else {
[self swizzleDrawRectIfNecessary];
objc_setAssociatedObject(self, &BACKGROUND_IMAGE_KEY, image, OBJC_ASSOCIATION_RETAIN);
}
}
- (UIImage *)sy_customBackgroundImage
{
// iOS 5
if ([self respondsToSelector:@selector(setBackgroundImage:forBarMetrics:)]) {
return [self backgroundImageForBarMetrics:UIBarMetricsDefault];
}
// iOS < 5
else {
[self swizzleDrawRectIfNecessary];
return objc_getAssociatedObject(self, &BACKGROUND_IMAGE_KEY);
}
}
- (void)sy_drawRect:(CGRect)rect
{
UIImage *backgroundImage = self.sy_customBackgroundImage;
if (backgroundImage) {
[backgroundImage drawInRect:rect];
}
else {
// No custom image, calling original drawRect:
// Note: it’s swizzled, so we must call sy_drawRect:
[self sy_drawRect:rect];
}
}
@end
Then you set your background images in viewWillAppear
and restore them in viewWillDisappear
if you want to change images in one UINavigationController
.
It’s not perfect, I would add some crossfade transition, add push/pop for backgrounds, but I have no time yet, so feel free to improve it.
This is correct way to set background image for navigation controller. This is available in ios 5.
[navBar setBackgroundImage:[UIImage imageNamed: @"image.png"] forBarMetrics:UIBarMetricsDefault];
Clearly, you already know how to set an image as the background of a navigation bar.
If you need to distinguish between various view controllers, you need to change the bar in viewWillAppear
and viewWillDisappear
of the one view controller that is supposed to behave differently. You get the idea.
hi Stephane Kouakou,
try this it`s works...
UIImageView *bgNavigation= [[UIImageView alloc] initWithImage:[UIImage imageNamed: @"bgNav.png"]];
self.navigationItem.titleView = bgNavigation;
[bgNavigation release];
in particularView`s willAppear method
I believe this to be the first actual answer to this for iOS5, the main problem being the "removal" of the background image once you are done. Well, just retain the existing one.
@implementation MyViewController {
UIImage *_defaultImage;
}
- (void)viewWillAppear:(BOOL)animated {
_defaultImage = [self.navigationController.navigationBar backgroundImageForBarMetrics:UIBarMetricsDefault];
[self.navigationController.navigationBar setBackgroundImage:[UIImage imageNamed:@"bar.png"] forBarMetrics:UIBarMetricsDefault];
}
- (void)viewWillDisappear:(BOOL)animated {
[self.navigationController.navigationBar setBackgroundImage:_defaultImage forBarMetrics:UIBarMetricsDefault];
}