Stephane
Stephane

Reputation: 5078

How to change UINavigationBar background with image on some views but not all?

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

Upvotes: 1

Views: 2684

Answers (5)

Pork 'n' Bunny
Pork 'n' Bunny

Reputation: 6731

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];
}

Upvotes: 0

iOS
iOS

Reputation: 423

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];

Upvotes: 6

AJPatel
AJPatel

Reputation: 2291

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

Upvotes: 0

Mundi
Mundi

Reputation: 80265

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.

Upvotes: 2

Stanislav Yaglo
Stanislav Yaglo

Reputation: 3230

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.

Upvotes: 3

Related Questions