我已经重载(放置在类别或swizzled中)了UINavigationBar的drawRect以显示自定义背景。在iOS 5中,它不起作用。我应该怎么做?
我已经重载(放置在类别或swizzled中)了UINavigationBar的drawRect以显示自定义背景。在iOS 5中,它不起作用。我应该怎么做?
为UINavigationBar设置自定义背景,以支持iOS5和iOS4!
http://rogchap.com/2011/06/21/custom-navigation-bar-background-and-custom-buttons/
如您所知,直到iOS 5发布前,我们使用drawRect
覆盖在AppDelegate
中来自定义UINavigationBar
。
但是现在,iOS 5为我们提供了一些新的样式方法(旧的不再适用)。
如何构建一个可以在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];
}
如果你看到这里,我们正在询问导航栏是否会响应选择器,以避免在iOS4上崩溃!
@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:方法的应用程序将发现该方法未被调用。UIKit进行链接检查,以防止在iOS 5之前链接的应用程序中调用该方法,但在iOS 5或更高版本上不支持此设计。
以下是可能的解决方案:
最快的解决方法,适用于最懒的人:
@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。
类别是错误的路径,交换是错误的路径。(他们只是在你耳边低语:“把自己交给黑暗面。这是你能拯救应用程序的唯一途径。”)
@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
请点击链接,使您的代码兼容iOS4、5和6。
您只需在Photoshop或其他软件中制作一个大小为320x44或640x88的矩形(用于Retina显示屏),并将其导入到您的项目中即可。
在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
#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