otherSiOS学习iOS学习

iOS 隐藏导航栏最佳实践

2017-09-20  本文已影响1389人  酱油不爱醋

最近项目里折腾了下隐藏导航栏的问题。折腾的难度没有预期的那么低。。。
现在在这里总结一下:

基础版

- (void)viewWillAppear:(BOOL)animated {
    [self.navigationController setNavigationBarHidden:YES animated:animated];
    [super viewWillAppear:animated];
}

- (void)viewWillDisappear:(BOOL)animated {
    [self.navigationController setNavigationBarHidden:NO animated:animated];
    [super viewWillDisappear:animated];
}

基础版使用系统自带的方法,优点是简单实用,能够解决返回的时候隐藏导航栏动画问题。这在隐藏页面在导航控制器中间的时候没有问题。但是如果页面是导航控制器的根视图控制器,而这个导航栏又处于tabbar控制器的某一栏里,当你从别的tabbar切换到这个控制器就会发现导航栏会跳一下。这里的处理就不那么简单了。(勘误,有网友指出,把[super viewWillAppear:animated]放到[self.navigationController setNavigationBarHidden:YES animated:animated]后面执行就可以解决tabbar跳动问题,待验证)

进阶版

进阶版是我找到的别人做法
iOS透明导航栏的平滑过渡(进阶版)大概看了下,这位哥们的思路是把导航栏搞成透明的。然后我就把他的category拖到了工程里。试用了下,结果发现不行。。。不行。。。恩,好吧,那我再换另一个教程,于是就找到了下面这位大哥的教程:
【iOS】让我们一次性解决导航栏的所有问题看标题就高大上啊。受此影响,我也给自己的这篇教程取了个高大上又装逼,然而并没有多少内涵的标题。。。好吧,这不是重点。重点是,我把它的东西拖进来了,发现还是不行。。。难道是我的姿势不对?- -,除了显示有问题之外,它用起来还特别卡。。。还要继承它的类,对我自己原来的项目倾入性还很大。

终极大招

恩, 好吧。经过一番思考,我自己提出了一套解决方案,基本思路如下:
这套方案里,我使用的还是setNavigationBarHidden: animated:还是这个方法。假设我们tabbar控制器里有3个控制器 A、B、C,C控制器需要隐藏导航栏,并且C控制器里有个按钮,可以push到D控制器,且D控制器需要显示导航栏。但是所以我们需要实现的就是,从A、B到C的时候,setNavigationBarHidden: animated:animated参数需要设置为NO,而从D控制器pop回C控制器的时候,需要设置为YES。这样就能完美解决动画问题。为了能够统一控制,且易于以后扩展到别的控制器,我把tabbarController跟navigationController做了继承,通过在navigationcontroller的代理方法- navigationController: willShowViewController: animated:里完成隐藏与现实导航栏的操作。这里我们需要判断我们是从A、B控制器到C控制器,还是从D控制器pop回C控制器。我的实现思路如下:我给BaseTabBarViewController设置了一个delayIndex属性来记录上一次tabbarController所在的index。然后我在BaseTabBarViewController的代理方法里设置delayIndex

- (BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController {
    self.delayIndex = self.selectedIndex;
    return YES;
}

由于这个代理方法执行的时候,页面还没有跳到选中的控制器,就完成了记录上一次选中标签的工作。这样,在navigationcontroller的代理方法里判断delayIndex如果是0或者1,那么就是从A或者B控制器过来的,这时候就不需要动画:

- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated{
    BOOL hiddenAnimate = NO;
    NSInteger count = ((BaseTabBarViewController *)viewController.tabBarController).delayIndex;
    if (count == 2) {
        hiddenAnimate = YES;
    }
    BOOL isShowHomePage = [viewController isKindOfClass:[SecondViewController class]];
    [self setNavigationBarHidden:isShowHomePage animated:hiddenAnimate];
}

接下来解决从D控制器pop回去需要动画的问题。这里我想到去判断navigationController的栈里如果有大于1个的控制器,那就说明是push出去了。这时候让delayIndex等于当前tabbarController的selectedIndex。就可以解决了。代码如下:

- (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated{
    if (viewController.tabBarController.selectedIndex == 2 && [self.viewControllers count] > 1) {
        ((BaseTabBarViewController *)viewController.tabBarController).delayIndex = viewController.tabBarController.selectedIndex;

    }
}

完成效果如下:

效果.gif

以上代码均已上传至本人GitHub,如有疑问,欢迎咨询。

上一篇 下一篇

猜你喜欢

热点阅读