动态修改NavigationBar的颜色

首先我们想到的肯定是在UISrollView的delegate方法

- (void)scrollViewDidScroll:(UIScrollView *)scrollView

根据当前的contentOffset更新navigationBar的backgroundColor即可.

思路

首先想到的是最常用的[UINavigationBar appearance],我们一般会在AppDelegate中使用它对navigationBar进行统一的设置。但是如果试一下,会发现在scrollViewDidScrollView中调用它并不能动态地改变navigationBar的颜色,原因是: iOS应用出现变化时,视图会进入一个窗口,它不能改变已经再一个窗口的外观。

我们换一个方法试试看,直接修改UINavigationBar的backgroudColor:

- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
UIColor *color = [UIColor redColor];
CGFloat offsetY = scrollView.contentOffset.y;
if (offsetY > 0) {
    CGFloat alpha = 1 - ((64 - offsetY) / 64);
    self.navigationController.navigationBar.backgroundColor = [color colorWithAlphaComponent:alpha];
} else {
     self.navigationController.navigationBar.backgroundColor = [color colorWithAlphaComponent:0];
        }
}

然后发现,怎么是。。。。。有一半咋没有颜色 ????这是神马情况???

动态修改NavigationBar的颜色_第1张图片

通过reveal查看其中的层级结构,发现NavigationBar上面有一个_UINavigationBarBackground的遮盖,正是它决定了navigationBar的背景色。

动态修改NavigationBar的颜色_第2张图片

那我们把这个view拿到,删除不就可以了么?继续尝试。

我们通过打印 self.navigationController.navigationBar.subviews看到navigationBar上有两个子控件。

"<_UINavigationBarBackground: 0x7fed90f43990; frame = (0 -20; 414 64); opaque = NO; autoresize = W;                     userInteractionEnabled = NO; layer = >",
"<_UINavigationBarBackIndicatorView: 0x7fed90d053f0; frame = (0 11.6667; 13 21); alpha = 0; opaque = NO;             userInteractionEnabled = NO; layer = >"

我们可以通过遍历把 _UINavigationBarBackground 拿到并删除即可

for (UIView *view in self.navigationController.navigationBar.subviews) {
    if ([view isKindOfClass:NSClassFromString(@"_UINavigationBarBackground")]) {
        [view removeFromSuperview];
    }
}

然后发现这样就可以了,不过状态栏还是白色的啊~~~

动态修改NavigationBar的颜色_第3张图片

这时我们改变下状态栏的颜色就好了,要修改状态栏的颜色比较麻烦,那我们可以直接在navigationBar上加上一层遮罩就好

UIView *overlay = [[UIView alloc] initWithFrame:CGRectMake(0, -20, [UIScreen mainScreen].bounds.size.width,20)];
overlay.backgroundColor = [UIColor redColor];
[self.navigationController.navigationBar insertSubview:overlay atIndex:0];

不过这么干的话,那就要修改两个控件颜色。。。。这样修改起来非常的麻烦,有没有什么好点的方法呢????

换一个思路

考虑到继承UINavigationBar使用起来会非常不便,我们决定用Category来实现,首先定义我们的category:

@interface UINavigationBar (BackgroundColor)
- (void)lt_setBackgroundColor:(UIColor *)backgroundColor;
@end

我们可以使用associatedObject将overlay动态地绑定到UINavigationBar的instance上,当调用lt_setBackgroundColor的时候,我们只要更新这个overlay就可以了

   static char overlayKey;
@implementation UINavigationBar (BackgroundColor)


- (UIView *)overlay
{    return objc_getAssociatedObject(self, &overlayKey);
}

- (void)setOverlay:(UIView *)overlay
{
objc_setAssociatedObject(self, &overlayKey, overlay, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

- (void)lt_setBackgroundColor:(UIColor *)backgroundColor
{    
    if (!self.overlay) {
    [self setBackgroundImage:[UIImage new] forBarMetrics:UIBarMetricsDefault];
    [self setShadowImage:[UIImage new]];             
    self.overlay = [[UIView alloc] initWithFrame:CGRectMake(0, -20, [UIScreen mainScreen].bounds.size.width, 64)];
    [self insertSubview:self.overlay atIndex:0];  
}   
        self.overlay.backgroundColor = backgroundColor;
}
@end

最后在scrollViewDidScroll中,我们就可以动态地修改UINavigationBar的backgroundColor了:

[self.navigationController.navigationBar lt_setBackgroundColor:[color colorWithAlphaComponent:alpha]];

这个方法是参考了 LTNavigationBar 第三方类库,这类库已经给我们封装好了这些方法,使用起来非常简单



文/Aeron_Xie(简书作者)
原文链接:http://www.jianshu.com/p/6f3bc1da18f3
著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。

你可能感兴趣的:(iOS基础)