zoukankan      html  css  js  c++  java
  • 动态修改UINavigationBar的背景色

    git:https://github.com/ltebean/LTNavigationBar

    动态修改UINavigationBar的背景色

    2015-04-09 09:10 编辑: suiling 分类:iOS开发 来源:Glow 技术团队博客
     3 1472

    这是我们最终想要得到的效果:

    1428390275361373.gif

    思路

    在UISrollView的delegate方法

    1
     - (void)scrollViewDidScroll:(UIScrollView *)scrollView

    中根据当前的contentOffset更新navigationBar的backgroundColor即可,so easy~

    开动

    那么我们来看看apple为我们提供了哪些API来设置navigationBar的颜色。

    首先想到的是最常用的[UINavigationBar appearance],我们一般会在AppDelegate中使用它对navigationBar进行统一的设置。但是如果试一下,会发现在scrollViewDidScrollView中调用它并不能动态地改变navigationBar的颜色,原因可以看一下Apple的doc:

    Use the UIAppearance protocol to get the appearance proxy for a class. You can customize the appearance of instances of a class by sending appearance modification messages to the class’s appearance proxy.

    但是:

    iOS applies appearance changes when a view enters a window, it doesn’t change the appearance of a view that’s already in a window. To change the appearance of a view that’s currently in a window, remove the view from the view hierarchy and then put it back.

    所以换一条路,直接修改UINavigationBar的backgroudColor:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    - (void)scrollViewDidScroll:(UIScrollView *)scrollView
    {
        UIColor *color = [UIColor blueColor];
        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];
        }
    }

    结果却是…… 

    2.jpg

    仔细观察,会发现navigationBar的高度是44,它的上方是statusBar,而且,navigationBar的上面还有一个未知的View……到底Apple是怎么实现UINavigationBar的呢,让我们一探究竟!

    在xcode的顶部菜单栏找到Debug > View Debugging > Capture View Hierarchy:

    1428390599183114.jpg

    1428390603214036.jpg

    原来UINavigationBar上有一个_UIBackDropView,正是它决定了navigationBar的背景色。

    那么我们是不是可以修改它的颜色呢,赶紧打开UINavigationBar.h,找了一圈,1428390838630372.jpg

    既然没有public的API,我们只能hack了!

    Hack

    我们的思路很简单,参照Apple的实现,在navigationBar的view hierarchy中插入一个view,通过它来控制在navigationBar的backgroundColor。

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

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

    实现:我们使用associatedObject将overlayView动态地绑定到UINavigationBar的instance上,当调用lt_setBackgroundColor的时候,我们只要更新这个overlayView就行啦~

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    @implementation UINavigationBar (BackgroundColor)static char overlayKey;
     
    - (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]];        // insert an overlay into the view hierarchy
            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了:

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

    完整的代码在这里

    写在最后

    UINavigationBar是一个比较特殊的view,它被系统高度集成,有时候定制起来并不那么方便。其实这个demo完全可以用另外一种方法实现,就是不用UINavigationBar,自己画一套UI。

    很多时候我们都会发现系统原生控件出现一些预料之外的行为,那么打开view debugging,找出原因,然后解决它!

  • 相关阅读:
    利用rqalpha完成一个股指期货的回测(二) 分钟数据获取和转换
    利用rqalpha完成一个股指期货的回测(一)
    Pandas
    SAR停损指标
    一些简单的指标
    协程--流畅的Python第16章读书笔记
    python初级(302) 8 列表(选择排序练习二)
    博客已转移至 http://blog.yemou.net/
    将博客搬至51CTO
    将博客搬至CSDN
  • 原文地址:https://www.cnblogs.com/lihaibo-Leao/p/4414072.html
Copyright © 2011-2022 走看看