Пользовательский фон UINavigationBar - PullRequest
50 голосов
/ 01 апреля 2009

Я пытался настроить пользовательский фон для всего моего NavigationBar (не только titleView), но изо всех сил.

Я нашел эту тему

http://discussions.apple.com/thread.jspa?threadID=1649012&tstart=0

Но я не уверен, как реализовать данный фрагмент кода. Код реализован как новый класс? Также, где я могу установить UINavigationController, так как у меня есть приложение, созданное с помощью шаблона NavigationView, чтобы оно не выполнялось в моем корневом контроллере, как в примере

Ответы [ 15 ]

44 голосов
/ 05 августа 2011

Уддхав и лефло правы. Этот код работает хорошо:

@interface CustomNavigationBar : UINavigationBar
@end

@implementation CustomNavigationBar
-(void) drawRect:(CGRect)rect 
{
    UIImage *image = [UIImage imageNamed: @"myNavBarImage"];
    [image drawInRect:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
}
@end

// this can go anywhere
+(UINavigationController*) myCustomNavigationController
{
  MyViewController *vc = [[[MyViewController alloc] init] autorelease];
  UINavigationController *nav = [[[NSBundle mainBundle] loadNibNamed:@"CustomNavigationController" owner:self options:nil] objectAtIndex:0];
  nav.viewControllers = [NSArray arrayWithObject:vc];
  return nav;
}

Вы должны создать CustomNavigationController.xib, поместить в него UINavigationController и изменить класс навигационной панели на «CustomNavigationBar».

31 голосов
/ 19 октября 2011

Вы должны использовать прокси «внешний вид» для изменения фона и других свойств стиля элементов управления, таких как UINavigationBar, UIToolBar и т. Д. В iOS 5.xx. Однако они недоступны для iOS 4.xx, поэтому для обратной совместимости вам нужно гибридное решение.

Если вы хотите поддерживать устройства как iOS 4.xx, так и iOS 5.xx (т. Е. Ваш DeploymentTarget равен 4.xx), вы должны быть осторожны при переводе вызова на внешний прокси-сервер, проверяя во время выполнения, Селектор внешнего вида присутствует или нет.

Вы можете сделать это:

//Customize the look of the UINavBar for iOS5 devices
if ([[UINavigationBar class]respondsToSelector:@selector(appearance)]) {
    [[UINavigationBar appearance] setBackgroundImage:[UIImage imageNamed:@"NavigationBar.png"] forBarMetrics:UIBarMetricsDefault];
}

Вы также должны оставить обходной путь iOS 4.xx, который вы, возможно, внедрили. Если вы внедрили обходной путь drawRect для устройств iOS 4.xx, как упомянуто @ludwigschubert, вы должны оставить это в:

@implementation UINavigationBar (BackgroundImage)
//This overridden implementation will patch up the NavBar with a custom Image instead of the title
- (void)drawRect:(CGRect)rect {
     UIImage *image = [UIImage imageNamed: @"NavigationBar.png"];
     [image drawInRect:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
}
@end

Таким образом NavBar будет выглядеть одинаково на устройствах iOS 4 и iOS 5.

29 голосов
/ 27 апреля 2010

Вам просто нужно перегрузить drawRect так:

@implementation UINavigationBar (CustomImage)
- (void)drawRect:(CGRect)rect {
    UIImage *image = [UIImage imageNamed: @"NavigationBar.png"];
    [image drawInRect:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
}
@end
26 голосов
/ 25 июля 2011

Реализация категории не рекомендуется. iOS5 может помочь решить эту проблему. Но для старых API вы можете -

  1. Подкласс UINavigationBar, чтобы сказать CustomNavBar и реализовать собственный drawRect из ответа Лития.
  2. Для всех основанных на IB UINavigationControllers, укажите CustomNavBar в качестве пользовательского класса для их UINavigationBar.
  3. Для всего кода на основе UINavigationControllers. Создайте XIB с UINavigationController и выполните второй шаг. Затем предоставьте заводской метод в коде, который загружает UINavigationController из пера и предоставит IBOutlet.

Например.

[[NSBundle mainBundle] loadNibNamed:@"CustomNavigationController" owner:self options:nil];
UINavigationController *navController = self.customNavigationController;
navController.viewControllers = [NSArray arrayWithObject:controller]
10 голосов
/ 13 февраля 2011

Вы также можете переопределить метод drawLayer:inContext: в классе категории UINavigationBar. Внутри метода drawLayer:inContext: вы можете нарисовать фоновое изображение, которое хотите использовать.

- (void) drawLayer:(CALayer *)layer inContext:(CGContextRef)context
{
    if ([self isMemberOfClass:[UINavigationBar class]] == NO) {
        return;
    }

    UIImage *image = (self.frame.size.width > 320) ?
                        [UINavigationBar bgImageLandscape] : [UINavigationBar bgImagePortrait];
    CGContextClip(context);
    CGContextTranslateCTM(context, 0, image.size.height);
    CGContextScaleCTM(context, 1.0, -1.0);
    CGContextDrawImage(context, CGRectMake(0, 0, self.frame.size.width, self.frame.size.height), image.CGImage);
}

И как полный демонстрационный проект Xcode по настройке внешнего вида UINavigationBar , это и , это может быть полезно.

4 голосов
/ 04 августа 2011

Реализация категории не будет работать в iOS5, вы должны использовать совет Уддхава Камбли для использования CustomNavbar на iOS ≤ 5.

4 голосов
/ 18 августа 2010

Я только что нашел эту запись в блоге, описывающую эту тему очень просто: http://web0.at/blog/?p=38

это мне очень помогло, они используют метод "drawRect" для настройки фона.

3 голосов
/ 27 ноября 2011

Всем тем, у кого проблемы с пользовательскими фонами UINavigationBar в iOS5, сделайте это в соответствующих методах viewDidLoad:

#if defined(__IPHONE_5_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_5_0
if ([self.navigationController.navigationBar respondsToSelector:@selector( setBackgroundImage:forBarMetrics:)]){
    [self.navigationController.navigationBar setBackgroundImage:[UIImage imageNamed:@"TitleBar"] forBarMetrics:UIBarMetricsDefault];
}
#endif

Обратите внимание, что в моем случае фоновое изображение было названо "TitleBar". Вы можете поместить любое имя вашего фонового изображения.

2 голосов
/ 14 октября 2011

В iOS5 значение zPosition (из UINavigationBar's самого глубокого слоя) изменяется. Так что если вы измените это zPosition, старый способ сработает.

например.

UINavigationBar *_bar = navigationController.navigationBar;

// Insert ImageView    
UIImage *_img = [UIImage imageNamed:@"navibar.png"];
UIImageView *_imgv = [[[UIImageView alloc] initWithImage:_img] autorelease];
_imgv.frame = _bar.bounds;

UIView *v = [[_bar subviews] objectAtIndex:0];
v.layer.zPosition = -FLT_MAX;

_imgv.layer.zPosition = -FLT_MAX+1;
[_bar insertSubview:_imgv atIndex:1];

Этот скрипт обрабатывает слой вида, поэтому Вам следует импортировать QuartzCore.

2 голосов
/ 31 августа 2011

Другой подход заключается в использовании делегата UINavigationController. Не требует переклассификации / перезаписи класса UINavigationBar:

/*
 in the place where you init the navigationController:
 fixer = [[AENavigationControllerDelegate alloc] init];
 navigationController.delegate = fixer;
*/

@interface AENavigationControllerDelegate : NSObject <UINavigationControllerDelegate>
@end

@implementation AENavigationControllerDelegate

#define bgImageTag 143

- (void)navigationController:(UINavigationController *)navigationController 
   didShowViewController:(UIViewController *)viewController 
                animated:(BOOL)animated
{
     //this is for the future for implementing with the appearance api:

    if ([[navigationController navigationBar] respondsToSelector:@selector(setBackgroundImage:forBarMetrics:)])
    {
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            [[navigationController navigationBar] setBackgroundImage:[UIImage imageNamed:@"header-logo-bg.png"]
                                                   forBarMetrics:UIBarMetricsDefault];
        });
 }
    else
        {
        UIImageView* imageView = (UIImageView*)[navigationController.navigationBar viewWithTag:bgImageTag];
        if(!imageView)
        {
            UIImage *image = [UIImage imageNamed:@"header-logo-bg.png"];
            imageView = [[[UIImageView alloc] initWithImage:image] autorelease];
            imageView.tag = bgImageTag;
        }

        [navigationController.navigationBar insertSubview:imageView atIndex:0];        
    }
}

@end

https://gist.github.com/1184147

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...