Как изменить фон UINavigationBar с изображением в некоторых представлениях, но не во всех?

Я хотел бы установить изображение в качестве фона UINavigationController, но большинство решений, которые я нашел, применяют фон в панели навигации для всех представлений в приложении. Можете ли вы дать код, который может помочь?

Спасибо за помощь,

Стефан


person Steve    schedule 28.10.2011    source источник


Ответы (5)


Вот быстрый и грязный способ, который я использую в одном из своих проектов (у меня нет необходимости поддерживать альбомную ориентацию). Я реализовал его с категорией до UINavigationBar методом swizzling. Работает на iOS 4 и 5 (на 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

Затем вы устанавливаете свои фоновые изображения в viewWillAppear и восстанавливаете их в viewWillDisappear, если хотите изменить изображения в одном UINavigationController.

Это не идеально, я бы добавил кроссфейд-переход, добавил пуш/поп для фона, но у меня пока нет времени, так что не стесняйтесь улучшать.

person Stanislav Yaglo    schedule 28.10.2011

Это правильный способ установить фоновое изображение для навигационного контроллера. Это доступно в iOS 5.

[navBar setBackgroundImage:[UIImage imageNamed: @"image.png"] forBarMetrics:UIBarMetricsDefault];
person iOS    schedule 13.01.2012
comment
Возможно, это не сработает, если вы хотите изменить только один фон uiview. Он работает для всех uiview навигационного контроллера. - person gdm; 27.06.2013
comment
Да, это может быть решением большинства проблем людей, но эта функция не может отключить фон. - person Pork 'n' Bunny; 14.08.2013

Очевидно, вы уже знаете, как установить изображение в качестве фона панели навигации.

Если вам нужно различать различные контроллеры представления, вам нужно изменить панель в viewWillAppear и viewWillDisappear одного контроллера представления, который должен вести себя по-разному. Вы поняли идею.

person Mundi    schedule 28.10.2011

привет Стефан Куаку,

попробуй это работает...

 UIImageView *bgNavigation= [[UIImageView alloc] initWithImage:[UIImage imageNamed: @"bgNav.png"]];    
    self.navigationItem.titleView = bgNavigation;    
    [bgNavigation release];

в частности метод willAppear представления

person AJPatel    schedule 28.10.2011
comment
titleView не для фона. - person Stanislav Yaglo; 28.10.2011
comment
Я имел в виду фон, а не titleView :) - person Steve; 28.10.2011

Я считаю, что это первый фактический ответ на этот вопрос для iOS5, основная проблема которого заключается в «удалении» фонового изображения после того, как вы закончите. Ну, просто сохранить существующий.

@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];
}
person Pork 'n' Bunny    schedule 14.08.2013