美文网首页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里面怎么还设置成系统原来的导航条呢?
  • af730d45fbdd:大神 工程中那个导航栏类的封装是你自己写的啊 :scream: 好厉害 好崇拜 :clap:
  • 马铃薯蜀黍:我写了一个自定义导航控制器,想替换系统的,却发现这个东西是只读的
    xiesj88:@马铃薯蜀黍 用KVC
  • 一场大雨:还是有点问题,侧滑过去一点,就变透明了,再回来,依然是透明的,需要滑动一下才会恢复~
    雪_晟:@一场大雨 加全屏手势 返回按钮什么的也就没有了
  • 38667a252b11:为什么要释放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
  • Steven_2016:不错不错~~
  • Dis丶Peer:这不错哦
  • Gavin94:写的真好,刚好最近要用到.赞一个
    just_xam::smirk:能帮到就好

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

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