简体   繁体   English

透明UINavigationBar下的自定义背景

[英]Custom background under transparent UINavigationBar

There is a custom UIImageView under "Black Translucent" UINavigationBar , but I'm not too happy with the result. 在“ Black Translucent” UINavigationBar下有一个自定义UIImageView ,但我对结果不太满意。 The custom image is not visible enough and while changing navigation bar alpha value brings it more visible, it makes the navigation bar title and buttons less visible. 自定义图像的可见度不足,并且更改导航栏的alpha值会使该图像更加可见,但使导航栏标题和按钮不那么可见。

Question: I want a fully visible custom UINavigationBar background image with fully visible bar title and buttons. 问题:我想要具有完全可见的栏标题和按钮的完全可见的自定义UINavigationBar背景图像。 Any ideas how would I get all of that? 有什么想法我怎么能得到所有这些?

Update: My solution was similar as these answers, but a bit different. 更新:我的解决方案与这些答案相似,但有所不同。 Don't want to accept my own answer as correct one, so blogged about it ( link ) at iLessons iLearned. 不想接受我自己的答案作为正确答案,所以在iLessons iLearned上通过博客发布了该链接链接 )。

I wanted a custom UINavigationBar background image too, and ended up solving it by: 我也想要自定义UINavigationBar背景图像,并通过以下方法解决了它:

  • In the UINavigationController's initialisation, I created a CALayer that had contents set to the background image, and the frame set accordingly. 在UINavigationController的初始化中,我创建了一个CALayer,其contents设置为背景图像,并且框架也进行了相应设置。
  • I added that layer to the UINavigationBar's layer (at index 0, in the background): [self.navigationBar.layer insertSublayer:imageLayer atIndex:0] 我将该层添加到了UINavigationBar的层(在后台索引0处): [self.navigationBar.layer insertSublayer:imageLayer atIndex:0]

At this point, it looks okay at first, but if you do any navigation, labels and buttons disappear behind the 'background' layer. 至此,乍看起来还不错,但是如果您进行任何导航,标签和按钮就会消失在“背景”层的后面。 So, 所以,

  • I created a subclass of CALayer that changed the behaviour of insertSublayer:atIndex: so that no layers are inserted beneath the background layer. 我创建了CALayer的子类,该子类更改了insertSublayer:atIndex:的行为,以便在背景层下不插入任何层。

Like this: 像这样:

 @implementation CTNavigationBarLayer 
 - (void)insertSublayer:(CALayer *)layer atIndex:(unsigned)idx {
     if ( idx == 0 ) idx = 1;
     [super insertSublayer:layer atIndex:idx];
 }
 - (void)addBackgroundLayer:(CALayer*)layer {
     [super insertSublayer:layer atIndex:0];
 }
 @end
  • Using a category on UINavigationBar, I overloaded the +layerClass method to return [CTNavigationBar class] , so the navigation bar uses the custom layer. 使用UINavigationBar上的类别,我重载了+layerClass方法以返回[CTNavigationBar class] ,因此导航栏使用了自定义图层。

Of course, this changes the behaviour of all UINavigationBars in your app, so if this isn't what you want, you'd want to seek an alternate way. 当然,这会更改应用程序中所有 UINavigationBars的行为,因此,如果这不是您想要的,那么您将想寻找一种替代方法。 You could subclass UINavigationBar, but then the only way to get that subclass to be used in a UINavigationController is via IB (or do some rather interesting mucking about to do it programmatically) 你可以继承UINavigationBar的,但后来只有这样,才能在一个UINavigationController使用该子类是通过IB(或做一些相当有趣的做编程)

  • Finally, back in the UINavigationController initialisation, I replaced the layer insertion with a call to the addBackgroundLayer: method I wrote. 最后,回到UINavigationController初始化,我用对我编写的addBackgroundLayer:方法的调用来替换了图层插入。

Using drawRect in a category for UINavigationBar won't work in iOS5. 在UINavigationBar类别中使用drawRect在iOS5中不起作用。 The way suggested by Apple is to create a subclass of UINavigationBar and use it in your NIB file. Apple建议的方法是创建UINavigationBar的子类,然后在您的NIB文件中使用它。

For the benefit of people coming along here a bit later, it's worth noting that iOS5 provides direct support for this kind of customization. 为了使以后再来这里的人们受益,值得注意的是,iOS5为这种定制提供了直接支持。 To change the image underlying the UINavigationBar, use 要更改UINavigationBar基础的图像,请使用

- (void)setBackgroundImage:(UIImage *)backgroundImage forBarMetrics:(UIBarMetrics)barMetrics

There's also a property 还有一个财产

@property(nonatomic, copy) NSDictionary *titleTextAttributes

for adjusting the title. 用于调整标题。 And you can use appearance proxies to make these changes pervasive in your app. 而且,您可以使用外观代理使这些更改在您的应用程序中普遍存在。 More discussion in WWDC 2011, Session 114, "Customizing the Appearance of UIKit Controls". 在WWDC 2011,会议114,“自定义UIKit控件的外观”中进行了更多讨论。

Before iOS5, the way you were supposed to it was by subclassing UINavigationBar. 在iOS5之前,您应该通过子类化UINavigationBar来实现。

You can also create a UINavigationBar category class and override the drawLayer:inContext: method. 您还可以创建UINavigationBar类别类,并重写drawLayer:inContext:方法。 Inside the drawLayer:inContext: method, you can draw the background image you want to use. 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);
}

For a complete demo Xcode project on customizing the appearance of UINavigationBar this and this might be helpful. 有关自定义UINavigationBar的外观的完整演示Xcode项目可能会有帮助。

如果您有多个UINavigationController(例如在UITabBar中),则需要为每个UINavigationBar使用不同的背景,则ardalahmet解决方案不是正确的解决方案,因为它使用的是UINavigationBar类别。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM