这篇文章,我主要是想提供另外一种思路,来变更一下UINavigationController的颜色。
我们知道,调用navigationBar的setBarTintColor这个方法是可以实现改变导航栏颜色的,但是苹果大神是如何实现这个效果的呢,我们不妨来猜一下。首先我们来看一个正常的导航栏的层级视图。
再看看我们使用了setBarTintColor这个方法之后的层级视图
神奇的来了,居然是在UIBackdropView上再加了2个View,而且是覆盖在_UIBackdropEffectView上面,而这个_UIBackdropEffectView就是毛玻璃效果那个View,是不是觉得很神奇!我TM当时也震颤了一下!现在也没有想通为什么苹果要这样做,希望有大神解释一下。
好了,接来下就说一下我的思考过程,顺便也记录一下我走的弯路。
首先,我的想法绝对不是增加一个View去覆盖,所以我就想到了改变上面的某个View的背景色,让navigationBar看起来像那么回事。
于是我想到了更改navigationBar的titleView。
通过各种设置,我达到了预期的效果。
1.自定义一个View
@interface YHCustomTitleView : UIView
@end
@implementation YHCustomTitleView
- (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
}
return self;
}
//解决左右各10个像素左右的空白
- (void)setFrame:(CGRect)frame {
[super setFrame:CGRectMake(0, 0, self.superview.bounds.size.width, self.superview.bounds.size.height)];
}
@end
2.替换titleView
YHCustomTitleView * view = [[YHCustomTitleView alloc] initWithFrame:(CGRectMake(0, 0, SCREEN_WIDTH, 64))];
view.backgroundColor = [UIColor orangeColor];
self.navigationItem.titleView = view;
3.发现坑了。。。。。麻痹。。。原来的返回按钮点不动了!!!!而且当你立刻看当前的层级视图时,根本找不到问题。
于是我就pop到这个页面,查看层级视图,发现原来返回按钮被覆盖住了
4.如果还要一根筋走下去,剩下的工作就是将这个自定义的titleView作为navigationBar,隐藏掉系统的返回按钮,自定义按钮上去了。这样一来,问题就更过多了,比如左划无法pop等等。
这个时候,我发现,如果我们就改它的_UINavigationBarBackgroud这个View的背景颜色,不就行了。浏览一下navigationBar的.h文件,发现并没有提供这个View,不过没关系,宝宝有runtime大法!我们看看navigationBar到底藏了哪些不愿意我们改的东西!
到底是不是它!拿出来看看!
好!事情发展到这一步,离结束就不远了,改掉它的背景色后发现还有个毛玻璃效果,问题不大!因为我们已经拿到了这个view,而effectView恰恰是_UIBackdropView的子视图,另外一个子视图是UIImageView,其实就是那条著名的阴影。影藏掉_UIBackdropView就ok了,上代码。
UIView * tempview = [self.navigationController.navigationBar valueForKey:@"_backgroundView"];
tempview.backgroundColor = [UIColor redColor];
for (UIView * subView in tempview.subviews) {
if (![subView isKindOfClass:[UIImageView class]]) {
subView.hidden = YES;
}
}
目前还没有发现这种方法会引起的bug,如果过段时间还没有发现,我就把它搞到项目中,应对产品经理搞得幺蛾子了!