美文网首页iOS精英班iOS收藏iOS技能
NavigationController已经洗干净了,就等你来

NavigationController已经洗干净了,就等你来

作者: si1ence | 来源:发表于2016-12-04 13:28 被阅读3361次

好久没有更新博客了,近日把项目中遇到的NavigationController 相关技术点梳理一下,与大家共同分享

首先来点基础的属性

一. 基本属性

  • 设置颜色
    如果项目中 Navigation 都是统一的,而你又懒得单独抽取一个BaseNavigationController,可以直接在 [appDelegate didFinishLaunchingWithOptions]方法中写
//设置NavigationBar背景颜色
[[UINavigationBar appearance] setBarTintColor:[UIColor redColor]];

// 通过富文本设置title 样式(这里也可以通过自定义Label,然后设置 titleView 来实现)
[[UINavigationBar appearance] setTitleTextAttributes:@{
                    NSForegroundColorAttributeName : [UIColor whiteColor]
                                                           }];

// 设置状态栏格式,如果 NavigationBar 为深色调,就设置为 UIBarStyleBlack,则状态栏显示为白色
[[UINavigationBar appearance] setBarStyle:UIBarStyleBlack];
  • 实现 NavigationBar 透明效果
    实现透明可能大家第一个想到的是 设置 alpha 值,但是由于设置了作为父控件的 NavigationBar 的透明度后,其子控件 BarButtonItem 也会随之改变,因此想要实现导航栏透明,但是 BarButtonItem 正常显示(类似 手机QQ 的好友动态页),可以采用下面的方法
// 设置一个空的图片背景图片,就能实现导航栏透明但是 BarButtonItem 正常显示
[self.navigationController.navigationBar setBackgroundImage:[UIImage new]
                                                forBarMetrics:UIBarMetricsDefault];

然而设置之后乍一看没问题,可仔细一看你会发现NavigationBar下面还有一条细线,这个细线就是shadow


快看那条淡淡的细线!
层级关系图

可通过以下代码来去掉

// 设置一个空的 shadowImage 来实现
self.navigationController.navigationBar.shadowImage = [UIImage new];

那么有同学可能要问了,一直透明的可以通过上述方法来实现,那如果想要随着 上拉距离的改变,实现其透明度动态变化要怎么做?

// 这个就要监听 scrollView 的 offset
// 然后获取到 NavigationBar复合视图 的显示子控件,动态改变其透明度
[[self.navigationController.navigationBar subviews] objectAtIndex:0].alpha = 0;

既然讲到这里了就说下来回 push 或 pop,以及使用手势来返回的时候,上下层级之间 NavigationBar 隐藏与否的设置,因为如果这里没处理好的话,会有一个黑条,或者直接显示下一层级的视图,体验特别差,这时候就需要通过动画的方式的在下一层级进行设置

- (void)viewWillAppear:(BOOL)animated{
    [super viewWillAppear:animated];
    // 当前 VC 需要显示 navigationBar 就设置为 NO,需要隐藏就设置为 YES
    [self.navigationController setNavigationBarHidden:YES animated:YES];
}
  • 侧滑手势相关
    很多时候,leftBarButtonItem需要自定义,因为默认的显示上一层级的title不一定是我们想要的,但是自定义改变之后,会发现侧滑返回的手势不好使了


#warning 这时候就需要在当前 VC 中设置手势代理了
self.interactivePopGestureRecognizer.delegate = self;

// 实现代理方法:返回 YES,则手势有效
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
    //当导航控制器的子控制器个数 大于1 手势才有效
    return self.childViewControllers.count > 1;
}
  • 由于项目中同一个 VC,有时候是 modal 出来的,有时候是 push 出来的,那么在这个VC中就要判断进行处理
NSArray *viewcontrollers=self.navigationController.viewControllers;
if (viewcontrollers.count > 1) {
    if ([viewcontrollers objectAtIndex:viewcontrollers.count - 1] == self) {
        // push方式
        [self.navigationController popViewControllerAnimated:YES];
    }
} else {    
    // present方式    
    [self dismissViewControllerAnimated:YES completion:nil];
}
  • 如果要实现如下效果的导航栏,设置 leftBarButtonItems 和 rightBarButtonItems 即可


    喂!焦点在 NavigationBar,老看 tableView 干啥!
  • 关于 rootVC 的 offset,先来看几个 ViewController 的属性


  • iOS7以后默认设置是 UIRectEdgeAll,translucent 的默认值是 true,这个组合会使 rootView 的布局从 (0, 0) 开始,就会造成 rootView 被 NavigationBar 遮挡住一部分,将 edgesForExtendedLayout 设置为 UIRectEdgeNone 即可解决问题

  • automaticallyAdjustsScrollViewInsets 默认值是 YES,表示在全屏下会自动将 第一个添加到 rootVC 的 ScrollView 的 contentInset 设置为 (64, 0, 0, 0),这样 scrollView 就不会被导航栏遮挡住了

二. 来回跳转

项目中有个需求是A push 到 B, B push 到 C, C pop 到 D,D 再 pop到 A,就好比这样:

类似这种交叉跳转的感觉
  • 首先 A push 到 B,直接使用
[self.navigationController pushViewController:B animated:YES];
// 此时 self.navigationController.childViewControllers = [A, B];
  • 然后 B push 到 C,同理
[self.navigationController pushViewController:C animated:YES];
// 此时 self.navigationController.childViewControllers = [A, B, C];
  • 现在要实现 C pop 到 D,由于 navigationController.childViewControllers 是只读的,因此不能直接对其进行操作


    navigationController.childViewControllers 是只读的
// 建立可变拷贝对象,然后进行替换操作
NSMutableArray *navChildMArr = [self.navigationController.childViewControllers mutableCopy];
[navChildMArr replaceObjectAtIndex:1 withObject:D];

// 当然,最后再将替换后的数组赋值回去不要忘了
[self.navigationController setViewControllers:navChildMArr animated:YES];

#warning 至于写上面这串代码的时机:写在 B push C 之后可以,写在 C 的 viewDidLoad() 方法中也可以

最后的效果如图

对,效果如图 就四这么简单!

如果有其他问题,可以在留言处写下来,不定期更新

相关文章

  • NavigationController已经洗干净了,就等你来

    好久没有更新博客了,近日把项目中遇到的NavigationController 相关技术点梳理一下,与大家共同分享...

  • iOS开发集锦preview(2017.03.01)

    1.暂未更新 2. NavigationController已经洗干净了,就等你来 作者: si1ence源码: ...

  • iOS开发集锦之 2017.03.24

    1.暂未更新 2. NavigationController已经洗干净了,就等你来 作者: si1ence源码: ...

  • 2019年6月15日

    这会儿整六点,衣服已经洗好,客厅的地板也拖干净了,孩子们仍然在熟睡,我现在来做题。

  • 洗澡(三)

    万万没有料到,虽然已经洗干净了,冲干净了,擦干净居然更加令人崩溃,如果说洗澡是湿冷,那擦干的过程就是干冷。 站在原...

  • 你什么时候来

    我已经把吧台打扫干净 你什么时候来 我的酒已温好 盐焗花生还在锅里冒泡 你什么时候来 等你太久了 你来 我定会...

  • 未来已来,等你来“艾”

    未来已来,等你来“艾” 刘晓娜 过去已去,未来已来,随着人工智能的不断发展,我们的生活也会发生...

  • 未来已来,等你来“艾”

    未来已来,等你来“艾” 刘晓娜 过去已去,未来已来,随着人工智能的不断发展,我们的生活也会发生...

  • 城已亮,等你来

    谁家见月能闲坐?何处闻灯不看来? 故乡的夜晚,灯火辉煌,故乡的城墙,人灯相映。 正所谓“有灯无月不娱人,有月无灯...

  • 等你来

    春日已去夏将至 我在这儿等你来 欢笑也好 沉默也好 只要是你 只要你来 白日已尽夜已临 我在这儿等你来 搞笑也好 ...

网友评论

  • 走着走着就会敲代码了:代码没意思,资源呢?
    si1ence:@走着走着就会敲代码了 资源更没意思。。。
  • EvanJq:举报了:smiley:
  • 暮雨云归_9911:
    点个赞!
  • ADELEX:[[self.navigationController.navigationBar subviews] objectAtIndex:0].alpha = 0; 用了这个之后导航栏部分变黑色是为什么?
    si1ence:@ADELEX 这个得看你具体代码了,看下层级关系对症下药
    ADELEX:@si1ence 这个要怎么设置才不显示黑色?延长tableview?
    si1ence:@ADELEX 把上面的view设置成透明的,底层的黑色就显示出来了
  • 口袋海贼王_:妈的,楼主我百度云盘链接。
    口袋海贼王_:@si1ence 求地址
    si1ence:@口袋海贼王_ 百度云都会被封得,老司机都用115网盘
  • 2018火:modal出来的控制器如果包装了一个导航控制器,这样判断不对。
    si1ence:@腕理路 有道理!:+1:
  • ebay_Happy:老司机留下种子
  • 1d2aa59a2e8b:色情还是反动:angry:
  • 6e62803aebc1:留图不留种...
    si1ence:@CruiseCo 我能说是我h5的同事抓到的么?
  • 一夜暴富两夜也行::clap: 老司机开车叫我
  • MrFire_:嗖嘎
  • 丶Runs:我只服老司机 这个要上首页投稿才行
  • 443718761557:老司机 就服你 求接待宝资源
    443718761557:@si1ence 昨天下下来看了一下,差评
    si1ence:@sp5 真心没有代码好看。。。
    qazws:@不愿透露姓名的白先生 9G的内容没多少能看的,还不如找老师的资源看,都特么又丑又搓。。。

本文标题:NavigationController已经洗干净了,就等你来

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