iOS 5.0中不调用UINavigationBar的drawRect

发布于 2024-12-08 18:17:10 字数 81 浏览 0 评论 0原文

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

I've overrided(placed in category, or swizzled) UINavigationBar's drawRect to show custom background. In iOS 5 it's not working. What should I do?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

鹿! 2024-12-15 18:17:10

为 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 发布之前,我们使用 AppDelegate 中重写 drawRect 以自定义 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];
}

如果您看到,这里我们询问导航栏是否会 respondToSelector 以避免 iOS4 上的崩溃!

Setting custom background for UINavigationBar to support iOS5 and iOS4 too!

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/


As you know, until iOS 5 came out, we used drawRect override in AppDelegate to customize UINavigationBar.
But know, iOS 5 give us some new method for styling (and old doesn’t work).

How to build app that will work on iOS 4 and iOS 5 with stylized UINavigationBar?

You must to do both!

In AppDelegate use this code:

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

and in viewDidLoad method for iOS5 (in your view implementation):

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

If you see, here we are asking if navbar will respondToSelector to avoid crash on iOS4!

一笑百媚生 2024-12-15 18:17:10

这是一个不太丑陋的解决方案,适用于 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

Here's a less-ugly solution that works for both iOS4 and 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
两人的回忆 2024-12-15 18:17:10

尝试阅读 iOS 5.0 发行说明

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

Try to read iOS 5.0 Release Notes

In iOS 5, the UINavigationBar, UIToolbar, and UITabBar implementations have changed so that the drawRect: method is not called unless it is implemented in a subclass. Apps that have re-implemented drawRect: in a category on any of these classes will find that the drawRect: method isn't called. UIKit does link-checking to keep the method from being called in apps linked before iOS 5 but does not support this design on iOS 5 or later.

时光瘦了 2024-12-15 18:17:10

有一些可能的解决方案:

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

@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的逻辑流程切换-
尽可能使用新的 API。

类别是错误的路径,Swizzling 是错误的路径。 (他们只是在你耳边低语:“把自己交给黑暗面。这是你拯救你的应用程序的唯一方法。”)

There's some possible solutions:

Quickest fix For laziest of us :

@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

Again. It works, but You shouldn't do it like this.

Another way, as suggested in WWDC'11 is to override UINavigationBar (Create MyNavigationBar) and initialize UINavigationController from xib like here :

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

And finally, use logic flow switch for iOS5.0 and iOS5.0-
Use new API where it's possible.

Categories is wrong path, Swizzling is wrong path. (They're just whispering in your ears:"Give yourself to the Dark Side. It is the only way you can save your apps.")

说谎友 2024-12-15 18:17:10
@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)设置任何自定义背景图像。

@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

The above swizzling will allow you to set any custom background image for the UINavigationBar(iOS5 & iOS4).

阳光的暖冬 2024-12-15 18:17:10

请按照此链接使您的代码与 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

Follow this link to make your code compatible with iOS4, 5 and 6.

You just have to make in Photoshop or other software a rectangular with the size of 320x44 or 640x88 (for retina display) and import it to your project

In AppDelegate use this code (in the header between #import and @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

In viewDidLoad use this code for iOS5 and 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
大姐,你呐 2024-12-15 18:17:10

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

After iOS 5 - (void)drawRect:(CGRect)rect is not called while we create category for UINavigationBar but you can call -(void)awakeFromNib and add all the code that you want to add.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文