UINavigationBar的drawRect在iOS 5.0中不被调用
我已经overrided(放在类别中,或调整)UINavigationBar的drawRect来显示自定义背景。 在iOS 5中,它不工作。 我该怎么办?
为UINavigationBar设置自定义背景以支持iOS5和iOS4!
http://rogchap.com/2011/06/21/custom-navigation-bar-background-and-custom-buttons/
如你所知,在iOS 5出来之前,我们在AppDelegate
使用了drawRect
override来自定义UINavigationBar
。 但是要知道,iOS 5为我们提供了一些新的样式devise方法(旧的方法不起作用)。
如何构build可在iOS 4和iOS 5上使用程式化UINavigationBar
?
你必须这样做!
在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]; }
如果你看到,在这里我们问是否navbar将respondToSelector,以避免iOS4的崩溃!
这是一个不太好看的解决scheme,适用于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
尝试阅读iOS 5.0发行说明
在iOS 5中,UINavigationBar,UIToolbar和UITabBar实现已更改,因此drawRect:方法不会被调用,除非它在子类中实现。 重新实现了drawRect的应用程序:在任何这些类的类别中都会发现不调用drawRect:方法。 UIKit会执行链接检查,以防止在iOS 5之前链接的应用程序中调用该方法,但不支持iOS 5或更高版本中的此devise。
有一些可能的解决scheme:
最快的解决scheme对于我们最懒惰的人:
@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(Create MyNavigationBar)并像这样从xib初始化UINavigationController:
http://www.iosdevnotes.com/2011/09/custom-uinavigationbars-techniques/
最后,为iOS5.0和iOS5.0使用逻辑stream程切换 – 在可能的地方使用新的API。
分类是错误的path,Swizzling是错误的path。 (他们只是在耳边低声说:“给自己一个黑暗的一面,这是保存你的应用程序的唯一方法。”)
@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
上面的swizzling将允许你为UINavigationBar(iOS5和iOS4)设置任何自定义的背景图片。
按照此链接 ,使您的代码与iOS4,5和6兼容。
您只需在Photoshop或其他软件中制作一个尺寸为320×44或640×88的矩形(用于视网膜显示)并将其导入到您的项目中
在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
在iOS 5之后- (void)drawRect:(CGRect)rect
在我们为UINavigationBar
创build类别时不会调用- (void)drawRect:(CGRect)rect
,但是可以调用-(void)awakeFromNib
并添加所有要添加的代码。