美文网首页iOS开发实践天生不是作曲家IOS开发
几句话实现导航栏透明渐变-iOS

几句话实现导航栏透明渐变-iOS

作者: just_xam | 来源:发表于2016-05-27 18:28 被阅读8706次

    首先我们来看下效果

    Gif1.gif

    一开始当我们什么只设置了一张图片作为它的头部视图的时候,它是这样的

    Picture1.png

    1.首当其冲的,我们先得把导航栏弄透明

    那么我们首先得知道,设置navigationBar的BackgroundColor为Clear是没用的,你可以试着设置它的clear,但是没用,原因一会儿我们就知道了

    而对于把导航栏设置为透明,网上大多数的方法是

    [self.navigationController.navigationBar setBackgroundImage:[UIImage new]
                                                  forBarMetrics:UIBarMetricsDefault];
     self.navigationController.navigationBar.shadowImage = [UIImage new];
    

    你可以运行这两句话到你的程序,你会发现这样确实是可以的,那么我们可以从中得到几个信息
    1.我们设置的是BackgroundImage,说明也许在我们的navigationBar上有一个ImageView的子视图,而我们的看到的导航栏实际上看到的就是这个图片,因此设置它为无图片我们就可以看到透明,而设置backgroundColor却不行

    2.我们还设置了shadowImage为无图,它其实就是导航栏下面的那根细线,如果你不写第二句话你则会看到一根线

    我们来看一下navigationBar的结构图

    Picture2.png

    从图中我们可以很清楚的看到,NavigationBar他背后是有一张类型为_UINavigationBarBackground(UIImageView的子类)的视图,我们平时看到的大部分其实都是它,第二个箭头那里的ImageView就是那根细线,他是加在我们背景的ImageView上面的,我们设置BackgroundImage其实就是设置_UINavigationBarBackground的image

    运行效果如图

    Picture3.png

    2.还得让它不仅仅是透明

    这,怎么整?我们有几种方案

      1. 设置渐变图片
        根据上面设置为透明的方法,我们最直接能想到的还是setBackgroundImage,根据滑动距离去设置 图片 的alpha,是的,我们是去设置图片,而不是设置UIView,这样的话就需要你不停的去生成新图片赋给BackgroundImage,这样感觉是不是会不太好?
    • 2.运行时动态绑定
      我们可以在运行时动态绑定他的背景视图,然后设置他的背景透明度,网上有一个通过类别方式动态绑定实现导航栏颜色渐变的三方框架,感兴趣的朋友可以自行去研究研究LTNavigation

    • 3.直接获取那张ImageView,然后设置他的透明度
      其实我们从结构图中可以看出来,他是NavigationBar的子视图,我们可以通过for...in循环遍历navigationBar.subviews,然后获得这个view.
      当然,更简单的,它其实就在subviews的第一个,即,我们可以这样

    barImageView = self.navigationController.navigationBar.subviews.firstObject
    

    我们可以用一个全局的imageView引用他,以免我们每次都要写一长串

    3.其实已经可以了

    我们还需要做什么?没错,最后一步,我们仅仅只需要在scrollViewDidScroll里面,根据偏移量来动态改变barImageView的背景颜色(或者透明度)就行了
    例如我们需要在-64(默认的最小偏移量)到200之间变化

    - (void)scrollViewDidScroll:(UIScrollView *)scrollView {
        CGFloat minAlphaOffset = - 64;
        CGFloat maxAlphaOffset = 200;
        CGFloat offset = scrollView.contentOffset.y;
        CGFloat alpha = (offset - minAlphaOffset) / (maxAlphaOffset - minAlphaOffset);
        _barImageView.alpha = alpha;
    }
    

    就这样你就可以实现我在文章一开始那个图片的效果了(其实并不是,tintColor和satusBarStyle还没变)

    Tips

    1. 你也可以动态的更改的状态栏和标题的颜色以和导航栏更匹配
    //状态栏
    [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];
    //标题颜色
    self.navigationController.navigationBar.titleTextAttributes = @{NSForegroundColorAttributeName : [UIColor someColor]}
    //导航栏子控件颜色
    self.navigationController.navigationBar.tintColor = [UIColor someColor];
    

    2.注意释放tableView 的 delegate(不然你进进出出时候会发现哪里好像不太对)

    - (void)viewWillAppear:(BOOL)animated {
        [super viewWillAppear:animated];
        self.tableView.delegate = self;
    }
    
    - (void)viewWillDisappear:(BOOL)animated {
        [super viewWillDisappear:animated];
        self.tableView.delegate = nil;
    }
    

    3.导航栏是公有的
    所以你可能需要在ViewWillDisappear里面再把导航栏设置为你需要的样子

    还有一件事情(This word Learn from Steve jobs)

    我自己封装了一些导航栏变化效果,使用简单,欢迎大家尝试MXNavigationBarManager

    Gif2-1.gif

    相关文章

      网友评论

      • 6c791e549784:[self sharedManager].saveImage = ((UIImageView *)navigationBar.subviews.firstObject).image;
        楼主照着你的demo写的蹦到这一行
        错误信息是:
        [_UIBarBackground image]: unrecognized selector sent to instance 0x7ffd09c0ae80
        具体怎么使用,我和你demo写的一样的啊,cocoapod导入的, storyboard创建的
        d922429c991f:找到问题了, pod 里免是1.1版本,demo 里面的是1.0版本。
        在初始化方法里面1.1 和 1.0 版本不同。

        1.0 :
        UINavigationBar *navigationBar = viewController.navigationController.navigationBar;
        [self sharedManager].selfNavigationController = viewController.navigationController;
        [self sharedManager].selfNavigationBar = navigationBar;
        [navigationBar setBackgroundImage:[UIImage new] forBarMetrics:UIBarMetricsDefault];
        [navigationBar setShadowImage:[UIImage new]];


        1.1:
        UINavigationBar *navigationBar = viewController.navigationController.navigationBar;
        [self sharedManager].saveImage = ((UIImageView *)navigationBar.subviews.firstObject).image;
        [self sharedManager].backgroundImageView = navigationBar.subviews.firstObject;
        [self sharedManager].selfNavigationBar = navigationBar;
        [navigationBar setBackgroundImage:[UIImage new] forBarMetrics:UIBarMetricsDefault];
        [navigationBar setShadowImage:[UIImage new]];

        1.1 版本具体原因我也不知道为什么,等博主解答吧~




        d922429c991f:我也遇到这个情况, 大神 你解决了没有?
      • 春暖花已开:博主,你好,在渐变透明的时候,右滑会导致返回键消失
      • 崠崠:手势滑动返回到一半 释放之后,navigationController会消失 作者
      • ChangeWorld:赞一个!
      • 西叶lv:当给导航栏添加了一个不透明的图片时,会造成子视图位置下移64点,这是为啥??
      • 沙暴送葬:前面你说设置渐变图片这样不是太好,但你又这样做?
      • 沙暴送葬:发现一个问题:在侧滑返回的时候,拖一下后立刻松手,渐变的效果全部消失,而且连侧滑也一起消失了
      • 来自南方的熊:我想问一下,为什么我跳到其他navigation的页面再回来就变成了原来没设置前的状态了
      • HideOnBush:请问如何设置navigationbar的imageview 的颜色
      • 雪_晟:如果侧滑 或者全屏返回,并没有退出当前界面, self.tableView.delegate = nil;
        [MXNavigationBarManager reStoreToSystemNavigationBar]; 放在viewDidDisappear 效果会更好
      • coder_那一抹刚吹过的风:兄弟 你对不起你们语文老师
        老司机Wicky:@中二九零后 首当其冲么
      • ITxiansheng:你好 1、reset 导航栏状态不能在viewWillAppear里面,右滑会调用这个方法。但是如果用户滑动一点,然后松手,复位。这时候导航栏被重置了。应该放在viewDidAppear里更合适吧 2.代码里offset发生变化后 总是新生成一个color image ,这样是不是消耗性能。如果颜色不变化的话,只改 alpha就可以把?
      • fe4a5edc73de:楼主你好!我想请教一下,当页面跳转到下一个页面,下一个页面的导航栏也变成透明了,请问如果下一个页面的导航栏不希望随着一起变化,有什么好方法吗?
        just_xam:@老男孩19910717 你可以看下我里面提到的运行时的那个demo,也可以看下底部的那个库,在进去页面时save,出去时restore
      • 郑明明:你这里也没写怎么设置背景颜色呢?????
      • 郑明明:没demo说这么没啥效果啊
      • 郑明明:demo呢
      • 左左4143:为什么进入的时候不是透明的 稍微动一下就变成透明的了? 其他的都正常
      • 西风颂:你好,麻烦问一下就是在push进去之后返回的时候上一页的导航栏会随着push那一页导航条的颜色变化,这个问题该怎么解决呢?
        just_xam:@西风颂 wiiappeal里面save,willdisappear里面restore
        西风颂:@西风颂 ViewWillDisappear
        西风颂:@西风颂 在viewwillappear里面怎么还设置成系统原来的导航条呢?
      • 永恒的知己:大神 工程中那个导航栏类的封装是你自己写的啊 :scream: 好厉害 好崇拜 :clap:
      • 马铃薯蜀黍:我写了一个自定义导航控制器,想替换系统的,却发现这个东西是只读的
        xiesj88:@马铃薯蜀黍 用KVC
      • 一场大雨:还是有点问题,侧滑过去一点,就变透明了,再回来,依然是透明的,需要滑动一下才会恢复~
        雪_晟:@一场大雨 加全屏手势 返回按钮什么的也就没有了
      • szweeee:为什么要释放tableview的代理
      • blurryssky:不错,虽然还有些小瑕疵,主要的目标达到了也讲清楚了
      • sheepcao:用delegate效果应该没有KVO好
      • 高浩浩浩浩浩浩:楼主你navigationBar的translucent不要设置为YES么?我如果用默认值,出来的效果是个灰色的导航条
        高浩浩浩浩浩浩:@just_xam 奥奥
        高浩浩浩浩浩浩:@高浩浩浩浩浩浩 估计是因为我设置了navigationBar的backgroundImage的原因。。。
        just_xam:@高浩浩浩浩浩浩 ios7以后translucent默认就是yes,如果你要适配ios6就得注意下
      • 肥猫记:3.直接获取那张ImageView,然后设置他的透明度
        其实我们从结构图中可以看出来,他是NavigationBar的子视图,我们可以通过for...in循环遍历navigationBar.subviews,然后获得这个view.

        我用forin循环怎么得不到呢~
        [self.navigationController.navigationBar setBackgroundImage:[UIImage new] forBarMetrics:UIBarMetricsDefault];

        for (id obj in self.navigationController.navigationBar.subviews) {
        if ([obj isKindOfClass:[UIImageView class]]) {
        self.naviBarImageView = (UIImageView *)obj;
        // return;
        }
        }
        //
        // self.naviBarImageView = [self.navigationController.navigationBar.subviews firstObject];
        self.naviBarImageView.backgroundColor = [UIColor blackColor];

        设置黑色的颜色没效果。但是用firstObject是有效果的。好奇怪
        just_xam:@SimonDeCft 它上面有两张ImageView,一个高度64,是背景的那张,还有一个高度21,是左边返回箭头的那张,你可以遍历的时候打印高度看下,然后对着结构图看你就明白了
      • 肥猫记:分析得很好。还是不知道为什么tablieview的delegata为什么要释放呢
        肥猫记:@just_xam [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];如果我不配置Plist就不能用这样改状态栏了,要怎么通过最新的方法来改状态栏的字体颜色呢?
        - (UIStatusBarStyle)preferredStatusBarStyle 这是iOS7.0之后推荐使用的,试了下会把整个导航栏都改成白色。
        just_xam:@SimonDeCft 你不在viewWillDisAppear里面释放代理,它会在离开页面之后还执行一次ScrollViewDidScroll
      • 开创未来86:mark 一下
      • helapu:分析好仔细啊 还有探索的感觉 工作中太需要这样的了
      • 5131ec23ee78:不错,学习了
      • LaiYoung_:一句话。透明navigation bar(navigationBar上面文字不消失),只是设置navigationBar的background的颜色的alpha。而透明navigationBar(隐藏文字)是设置navigationBar的alpha
      • JoeWcc:不错
      • lovedrose:剛剛要用,謝謝作者
      • 28a2a2c5f043:很详细
      • 瑞廷:不错不错
      • STDawn:mark
      • 达若漠沙:不错不错~~
      • Dis丶Peer:这不错哦
      • Gavin94:写的真好,刚好最近要用到.赞一个
        just_xam::smirk:能帮到就好

      本文标题:几句话实现导航栏透明渐变-iOS

      本文链接:https://www.haomeiwen.com/subject/bocfdttx.html