如何创建透明的UINavigationBar

要点

使用setBackgroundImage:*相关方法:

  1. - (void)setBackgroundImage:(nullable UIImage *)backgroundImage forBarMetrics:(UIBarMetrics)barMetrics
  2. - (void)setBackgroundImage:(nullable UIImage *)backgroundImage forBarPosition:(UIBarPosition)barPosition barMetrics:(UIBarMetrics)barMetrics

并结合使用shadowImage 属性:

@property(nullable, nonatomic,strong) UIImage *shadowImage

通过上述方法及属性,将背景图片阴影图片设置为透明图片,就能达到目的。

如果手头上没有透明图片,可以引入UIImage类别,通过代码,生成透明图片。例如:

UIImage+INB.h

1
2
3
4
5
6
7
#import <UIKit/UIKit.h>

@interface UIImage (INB)
+ (UIImage *)imageWithColor:(UIColor *)color size:(CGSize)size cornerRadius:(CGFloat)radius;
+ (UIImage *)imageWithColor:(UIColor *)color size:(CGSize)size;
+ (UIImage *)imageWithColor:(UIColor *)color;
@end

UIImage+INB.m

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#import "UIImage+INB.h"

@implementation UIImage (INB)
+ (UIImage *)imageWithColor:(UIColor *)color size:(CGSize)size cornerRadius:(CGFloat)radius {
UIGraphicsBeginImageContextWithOptions(size, NO, 0);
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextSaveGState(ctx);
if (radius > 0.0f && radius <= size.width && radius <= size.height) {
UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(0, 0, size.width, size.height) cornerRadius:radius];
[color setFill];
[path fill];
} else {
CGContextSetFillColorWithColor(ctx, color.CGColor);
CGContextFillRect(ctx, CGRectMake(0, 0, size.width, size.height));
}
CGContextRestoreGState(ctx);
UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return img;
}

+ (UIImage *)imageWithColor:(UIColor *)color size:(CGSize)size {
return [UIImage imageWithColor:color size:size cornerRadius:0.0f];
}

+ (UIImage *)imageWithColor:(UIColor *)color {
return [UIImage imageWithColor:color size:CGSizeMake(1, 1)];
}
@end

注意,通过上面的方法创建图片时,UIKIT_EXTERN void UIGraphicsBeginImageContextWithOptions(CGSize size, BOOL opaque, CGFloat scale)函数的opaque参数一定要设置为NO,只有这样,图片的alpha通道才会起作用,进而才能创建出透明图片。

先看看初步的代码及效果:

1
2
3
4
5
6
7
8
- (void)viewDidLoad {
[super viewDidLoad];

self.view.backgroundColor = [UIColor greenColor];
UINavigationBar *navBar = self.navigationController.navigationBar;
UIImage *bgImg = [UIImage imageWithColor:[UIColor redColor]];
[navBar setBackgroundImage:bgImg forBarMetrics:UIBarMetricsDefault];
}

transparent_nav_bar_320_568_1.png

现在将背景图片设置为透明图片:

1
2
3
4
5
6
7
8
9
- (void)viewDidLoad {
[super viewDidLoad];

self.view.backgroundColor = [UIColor greenColor];
UINavigationBar *navBar = self.navigationController.navigationBar;
UIColor *transparentColor = [UIColor colorWithWhite:0 alpha:0];
UIImage *transparentImg = [UIImage imageWithColor:transparentColor];
[navBar setBackgroundImage:transparentImg forBarMetrics:UIBarMetricsDefault];
}

transparent_nav_bar_320_568_2.png

可以看到,UINavigationBar的底部会有一条“黑线”,这条“黑线”其实是一个UIImageView

请看Debug View Hierarchy的结果:

transparent_nav_bar_bottom_img_view.png

现在,只要将这条“黑线”去掉或隐藏掉就能达到最终的目的。做成看起来像是去掉或隐藏掉也是可以的。

方法比较多。例如使用navBar.layer.masksToBounds = YES,但将这种方式用在此处并不是我所建议的。确切地说,此处的“黑线”就是shadowImage所产生的效果。

修改一下代码,就可以看出来:

1
2
3
4
5
6
7
8
9
10
11
- (void)viewDidLoad {
[super viewDidLoad];

self.view.backgroundColor = [UIColor greenColor];
UINavigationBar *navBar = self.navigationController.navigationBar;
UIColor *transparentColor = [UIColor colorWithWhite:0 alpha:0];
UIImage *transparentImg = [UIImage imageWithColor:transparentColor];
[navBar setBackgroundImage:transparentImg forBarMetrics:UIBarMetricsDefault];
UIImage *shadowImg = [UIImage imageWithColor:[UIColor redColor] size:CGSizeMake(1, 20)];
navBar.shadowImage = shadowImg;
}

其效果如下:

transparent_nav_bar_320_568_3.png

Debug View Hierarchy的结果如下:

transparent_nav_bar_bottom_shadow_img_view.png

明白了这一点,将shadowImage设置为之前所生成的transparentImg透明图片即可。

1
2
3
4
5
6
7
8
9
10
- (void)viewDidLoad {
[super viewDidLoad];

self.view.backgroundColor = [UIColor greenColor];
UINavigationBar *navBar = self.navigationController.navigationBar;
UIColor *transparentColor = [UIColor colorWithWhite:0 alpha:0];
UIImage *transparentImg = [UIImage imageWithColor:transparentColor];
[navBar setBackgroundImage:transparentImg forBarMetrics:UIBarMetricsDefault];
navBar.shadowImage = transparentImg;
}

如何创建透明的UINavigationBar
https://daniate.github.io/2015/08/04/如何创建透明的UINavigationBar/
作者
Daniate
发布于
2015年8月4日
许可协议