UINavigationBar 问题的自定义背景

Posted

技术标签:

【中文标题】UINavigationBar 问题的自定义背景【英文标题】:Custom background for UINavigationBar problems 【发布时间】:2009-09-16 12:14:57 【问题描述】:

我已经设法通过使用以下方法向导航栏添加自定义背景:

UIImageView *iv = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"UINavigationBar.png"]];
[myViewController.navigationBar insertSubview:iv atIndex:0];
[iv release];

这很好用,我可以看到标题和按钮。但是,当我向下钻取一层然后返回根目录时,按钮被隐藏,但标题仍然可见。似乎导航栏图像覆盖了按钮项。

我很困惑,因为我将它插入底部,所以我会假设当导航项被推送和弹出时,它们显示在导航栏中的其他视图之上。

有什么想法吗?

谢谢,

迈克

【问题讨论】:

【参考方案1】:

根据here 的描述,我建议在导航栏中添加一个类别。

@implementation UINavigationBar (UINavigationBarCategory)

- (void)drawRect:(CGRect)rect 
    // Drawing code 
    UIImage *img = [UIImage imageNamed: @"navbar_background.png"];
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextDrawImage(context, CGRectMake(0, 0, 320, self.frame.size.height), img.CGImage);


@end

【讨论】:

谢谢!它正在工作,只是导航栏似乎在图像顶部添加了从暗到亮的渐变!有什么办法可以消除这种影响? 实际上,它似乎正在将 PNG 颠倒过来!?有什么想法吗? 啊知道了...你需要使用 [img drawInRect:CGRectMake(0, 0, 320, self.frame.size.height)];而不是 CGContextDrawImage()! 您可以将上述代码添加到您的 appdelegate.m 文件的底部。之所以提到这一点,是因为我没有通过谷歌搜索得到这个。 @Michael Waterfall [img drawInRect:rect];【参考方案2】:

ios 5 上这不起作用,但好消息是有一种简单的方法可以做到这一点

[[UINavigationBar appearance] setBackgroundImage:[UIImage imageNamed:@"name"] forBarMetrics:UIBarMetricsDefault];

注意:这仅适用于 iOS 5 及更高版本,因此如果您想向后兼容,请确保检查 iOS 版本。

【讨论】:

【参考方案3】:

NavigationBar 的子视图在不断变化,我的意思是每个视图都会出现/消失,因此您不应期望在子视图数组的索引 0 处添加图像视图。

您可以尝试在 viewDidAppear 中添加它(在每个管理导航项 /: 的视图控制器中):

NSLog(@"navbar's subviews before \n %@",[[[self navigationController] navigationBar] subviews]);

for (UIImageView *imgv in [[[self navigationController] navigationBar] subviews]) 
    [[[self navigationController] navigationBar] sendSubviewToBack:imgv];


NSLog(@"navbar's subviews after \n %@",[[[self navigationController] navigationBar] subviews]);

我使用了Hauek's 解决方案,但是当酒吧在其他控制器中具有不同的风格时,它可能会出现一些小问题,无论如何,这都不是最好的选择。

希望它有所帮助,至少可以了解您所做的事情为什么不起作用,

【讨论】:

【参考方案4】:

您可以覆盖 UINavigationBar 类别类中的 drawLayer:inContext: 方法,而不是在 drawRect: 中执行此操作。在 drawLayer:inContext: 方法中,您可以绘制您想要使用的背景图像。如果您的应用支持多种界面方向,您还可以为纵向和横向界面方向选择不同的图像。

- (void) drawLayer:(CALayer *)layer inContext:(CGContextRef)context

    if ([self isMemberOfClass:[UINavigationBar class]] == NO) 
        return;
    

    UIImage *image = (self.frame.size.width > 320) ?
                        [UINavigationBar bgImageLandscape] : [UINavigationBar bgImagePortrait];
    CGContextClip(context);
    CGContextTranslateCTM(context, 0, image.size.height);
    CGContextScaleCTM(context, 1.0, -1.0);
    CGContextDrawImage(context, CGRectMake(0, 0, self.frame.size.width, self.frame.size.height), image.CGImage);

This complete demo Xcode project 关于自定义 UINavigationBar 的外观也可能会有所帮助。

【讨论】:

【参考方案5】:

接下来是向 UINavigationBar 添加新背景的方法。

/////////
 UINavigationController *navController = [[UINavigationController alloc] init];
 UINavigationBar*bar=[navController navigationBar]; // get navigation bar 
  NSArray*barSubview=[bar subviews]; // get all subviews of bar
 UIView*backView=[arr objectAtIndex:0]; // at index 0 lying background view of our bar
 backView.alpha=0.0f;// set alpha to 0 and it will become invisible

    UIImageView*imgView=[[UIImageView alloc] initWithImage:[UIImage imageNamed:@"top-bar.png"]];// create the image view that we will insers as subbview in our bar
    imgView.frame=CGRectMake(0, 0, 320, 44);
    [bar insertSubview:imgView atIndex:0];// and it will be out new background
    [imgView release];

【讨论】:

以上是关于UINavigationBar 问题的自定义背景的主要内容,如果未能解决你的问题,请参考以下文章

iPhone - 如何使用我的纹理背景自定义 UINavigationBar 后退按钮

使用 UINavigationController 默认 UIToolbar 的自定义背景

iPad 上 UIPopoverController 中 UIActionSheet 的自定义背景

删除 MFMailComposer 和 MFMessageComposer 的自定义 UINavigationBar

rightBarButtonItem.enabled 从 uinavigationbar 中删除我的自定义层

UINavigationBar setItems/pushNavigationItem/popNavigationItem 的自定义动画?