UINavigationBar的drawRect未在iOS 5.0中调用

时间:2011-10-05 06:28:13

标签: iphone ios background uinavigationbar ios5

我覆盖(放置在类别中或调配)UINavigationBar drawRect以显示自定义背景。在iOS 5中,它不起作用。我该怎么办?

7 个答案:

答案 0 :(得分:26)

为UINavigationBar设置自定义背景以支持iOS5和iOS4!

<击> http://www.mladjanantic.com/setting-custom-background-for-uinavigationbar-what-will-work-on-ios5-and-ios4-too/

http://rogchap.com/2011/06/21/custom-navigation-bar-background-and-custom-buttons/


如您所知,在iOS 5发布之前,我们在drawRect中使用AppDelegate覆盖来自定义UINavigationBar。 但是要知道,iOS 5为我们提供了一些新的样式方法(旧的方法不起作用)。

如何使用程式化的UINavigationBar构建适用于iOS 4和iOS 5的应用程序?

你必须同时做到这两点!

AppDelegate中使用此代码:

@implementation UINavigationBar (UINavigationBarCategory)
- (void)drawRect:(CGRect)rect {
UIImage *img = [UIImage imageNamed:@"navbar.png"];
[img drawInRect:rect];
}
@end

和iOS5的viewDidLoad方法(在您的视图实现中):

if ([self.navigationController.navigationBar respondsToSelector:@selector( setBackgroundImage:forBarMetrics:)]){
[self.navigationController.navigationBar setBackgroundImage:[UIImage imageNamed:@"navbar.png"] forBarMetrics:UIBarMetricsDefault];
}

如果你看到,我们在这里询问导航栏是否会响应ToSelector以避免iOS4崩溃!

答案 1 :(得分:12)

这是一个适用于iOS4和5的不太丑陋的解决方案:

@implementation UINavigationBar (CustomBackground)

- (UIImage *)barBackground
{
    return [UIImage imageNamed:@"top-navigation-bar.png"];
}

- (void)didMoveToSuperview
{
    //iOS5 only
    if ([self respondsToSelector:@selector(setBackgroundImage:forBarMetrics:)])
    {
        [self setBackgroundImage:[self barBackground] forBarMetrics:UIBarMetricsDefault];
    }
}

//this doesn't work on iOS5 but is needed for iOS4 and earlier
- (void)drawRect:(CGRect)rect
{
    //draw image
    [[self barBackground] drawInRect:rect];
}

@end

答案 2 :(得分:11)

尝试阅读iOS 5.0 Release Notes

  

在iOS 5中,UINavigationBar,UIToolbar和UITabBar实现已更改,因此除非在子类中实现,否则不会调用drawRect:方法。已重新实现drawRect的应用程序:在任何这些类的类别中将发现未调用drawRect:方法。 UIKit进行链接检查以防止在iOS 5之前链接的应用程序中调用该方法,但在iOS 5或更高版本上不支持此设计。

答案 3 :(得分:8)

有一些可能的解决方案:

最快的解决方案对于我们最懒的人:

@interface MyNavigationBar : UINavigationBar

@end

@implementation MyNavigationBar

- (void)drawRect:(CGRect)rect {

}

@end

@implementation UINavigationBar (BecauseIMLazyHacks)
/*
 Another Ugly hack for iOS 5.0 support
*/
+ (Class)class {
  return NSClassFromString(@"MyNavigationBar");
}

-(void)drawRect:(CGRect)rect {

  CGContextRef context = UIGraphicsGetCurrentContext();
  CGContextTranslateCTM(context, 0, self.frame.size.height);
  CGContextScaleCTM(context, 1.0, -1.0);

  CGContextDrawImage(context, CGRectMake(0, 0, 
  self.frame.size.width, self.frame.size.height), barBackground.CGImage);      

}
@end

再次。它有效,但你不应该这样做。

另一种方式,正如WWDC'11中所建议的那样,重写UINavigationBar(创建MyNavigationBar)并从xib初始化UINavigationController,如下所示:

  

http://www.iosdevnotes.com/2011/09/custom-uinavigationbars-techniques/

最后,使用iOS5.0和iOS5.0的逻辑流程开关 - 尽可能使用新的API。

类别是错误的路径,Swizzling是错误的路径。 (他们只是在你耳边窃窃私语:“把自己带到黑暗面。这是你保存应用程序的唯一方法。”)

答案 4 :(得分:1)

@implementation UINavigationBar (MyCustomNavBar)

- (void)setBackgroudImage:(UIImage*)image
{
    CGSize imageSize = [image size];
    self.frame = CGRectMake(self.frame.origin.x, self.frame.origin.y, self.frame.size.width, imageSize.height);
    UIImageView *backgroundImage = [[UIImageView alloc] initWithImage:image];
    backgroundImage.frame = self.bounds;
    [self addSubview:backgroundImage];
    [backgroundImage release];
}
@end

上述调配将允许您为UINavigationBar(iOS5和iOS4)设置任何自定义背景图像。

答案 5 :(得分:0)

按照此link使您的代码与iOS4,5和6兼容。

您只需在Photoshop或其他软件中制作尺寸为320x44或640x88的矩形(用于视网膜显示)并将其导入您的项目

在AppDelegate中使用此代码(在#import和@implementation AppDelegate之间的标题中):

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

在viewDidLoad中,将此代码用于iOS5和iOS6:

#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:@"top_bar.png"] forBarMetrics:UIBarMetricsDefault];
    }
#endif

答案 6 :(得分:0)

在我们为- (void)drawRect:(CGRect)rect创建类别时未调用iOS 5 UINavigationBar,但您可以调用-(void)awakeFromNib并添加您要添加​​的所有代码。