我覆盖(放置在类别中或调配)UINavigationBar drawRect以显示自定义背景。在iOS 5中,它不起作用。我该怎么办?
答案 0 :(得分:26)
为UINavigationBar设置自定义背景以支持iOS5和iOS4!
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中,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
并添加您要添加的所有代码。