【问题标题】:How to set an image as Navigation Bar Background without using a drawRect category?如何在不使用 drawRect 类别的情况下将图像设置为导航栏背景?
【发布时间】:2026-01-17 17:25:01
【问题描述】:

我想为我的 iphone 应用程序的导航栏设置图像背景。大多数解决方案建议在以下类别中使用 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

但是,Apple 不建议这样做。还有什么建议吗?

感谢您的帮助,

斯蒂芬

【问题讨论】:

    标签: iphone ios ios4 uinavigationcontroller uinavigationbar


    【解决方案1】:

    Apple 强烈建议我们使用子类而不是类别(WWDC 2011,Session 123)。

    创建一个实现drawRect: 方法的子类,并将导航栏的类设置为您的自定义类:

    • 如果您在 Interface Builder 中工作,请更改检查器中的类
    • 如果您创建一个独立的导航栏(没有导航控制器),请实例化您的自定义类
    • 如果您以编程方式创建导航控制器,则可以利用 ObjC 运行时。

    运行时类切换:

     #import <objc/runtime.h>
     ...
     object_setClass(theNavController.navigationBar, [CustomNavigationBar class]);
    

    您还应该避免在drawRect: 中每次都使用[UIImage imageNamed:...],因为它可能会影响性能(对于动画)。将其缓存在 ivar 中:

     if (!bgImage) {
         bgImage = [[UIImage imageNamed:@"NavigationBar.png"] retain];
     }
     [bgImage drawInRect:...];
    

    (并在 dealloc 中释放)

    注意:由于 iOS 5 仍处于保密协议下,我无法提及如何轻松添加背景图像。查看 UINavigationBar 的文档。

    【讨论】:

    • iOS5 新 api 不缩放图像。 :-(
    • @Seymour 是的,我也注意到了这一点。我改用 320*44 的图像。我可能会提出功能请求。
    • 您可以在设置 UIImage 之前将其调整为导航栏的大小——这种方式对我来说效果很好
    【解决方案2】:

    测试代码:100% 有效

    在您的 ViewDidLoad 中

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

    注意:urNavBarImage 应该是导航栏的精确大小。像这样你可以更改每个 Viewcontroller 导航栏。

    【讨论】:

      【解决方案3】:

      我已经为 UINavigationBar 创建了一个自定义类别,如下所示

      UINavigationBar+CustomImage.h
      
      #import <UIKit/UIKit.h>
      
      @interface UINavigationBar (CustomImage)
          - (void) setBackgroundImage:(UIImage*)image;
          - (void) clearBackgroundImage;
          - (void) removeIfImage:(id)sender;
      @end
      
      UINavigationBar+CustomImage.m
      
      #import "UINavigationBar+CustomImage.h"
      
      @implementation UINavigationBar (CustomImage)
      
      - (void) setBackgroundImage:(UIImage*)image {
          if (image == NULL) return;
          UIImageView *imageView = [[UIImageView alloc] initWithImage:image];
          imageView.frame = CGRectMake(110,5,100,30);
          [self addSubview:imageView];
          [imageView release];
      }
      
      - (void) clearBackgroundImage {
          NSArray *subviews = [self subviews];
          for (int i=0; i<[subviews count]; i++) {
              if ([[subviews objectAtIndex:i]  isMemberOfClass:[UIImageView class]]) {
              [[subviews objectAtIndex:i] removeFromSuperview];
          }
         }    
      }
      
      @end
      

      我从 UINavigationController 调用它

      [[navController navigationBar] performSelectorInBackground:@selector(setBackgroundImage:) withObject:image];
      

      【讨论】:

        最近更新 更多