How to change UINavigationBar background with imag

2019-08-05 05:03发布

问题:

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

回答1:

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.



回答2:

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


回答3:

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.



回答4:

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



回答5:

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