iOS隐藏导航栏

作者: 平原河流 | 来源:发表于2017-08-10 15:05 被阅读439次

    UINavigationController和UITabBarController是iOS开发中常用的两种视图控制器,主要用来控制UI界面流程跳转。
    在开发过程中,经常会遇到导航栏和标签栏,以及工具栏的显示和隐藏问题。

    本文主要介绍导航栏的显示与隐藏问题。
    以下是我整理的与导航栏显示与隐藏相关的控件组织图:


    UINavigationController

    通过上图可以看出:
    1、UINavigationController继承于UIViewController;
    2、UINavigationController包含viewControllers(UIViewController数组)、UINavigationBar、UIToolbar;
    3、UINavigationBar管理items(UINavigationItem数组);
    4、UIViewController包含UINavigationItem。

    下图能更好的理解UINavigationController组织结构


    UINavigationController

    以下介绍三种隐藏导航栏方法:

    方法一:
    @property(nonatomic,getter=isNavigationBarHidden) BOOL navigationBarHidden;
    - (void)setNavigationBarHidden:(BOOL)hidden animated:(BOOL)animated; 
    @property(nonatomic,readonly) UINavigationBar *navigationBar;
    

    使用UINavigationController的navigationBarHidden属性获取隐藏导航方法。常用于以下方法中

    - (void)viewWillAppear:(BOOL)animated; 
    - (void)viewDidAppear:(BOOL)animated; 
    - (void)viewWillDisappear:(BOOL)animated; 
    - (void)viewDidDisappear:(BOOL)animated;
    

    当然还有实现UINavigationControllerDelegate,在代理方法中通过判断showViewController类型,来控制显示。

    // Called when the navigation controller shows a new top view controller via a push, pop or setting of the view controller stack.
    - (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated;
    - (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated;
    

    这种隐藏方式在滑动过程中(iOS 7以后),会出现过渡不自然现象。(现不建议使用)

    方法二:

    使用UINavigationController+FDFullscreenPopGesture
    该类重写了UINavigationController的+ (void)load;方法。
    具体可参照以下代码:

    + (void)load
    {
        // Inject "-pushViewController:animated:"
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            Class class = [self class];
            
            SEL originalSelector = @selector(pushViewController:animated:);
            SEL swizzledSelector = @selector(fd_pushViewController:animated:);
            
            Method originalMethod = class_getInstanceMethod(class, originalSelector);
            Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);
            
            BOOL success = class_addMethod(class, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod));
            if (success) {
                class_replaceMethod(class, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod));
            } else {
                method_exchangeImplementations(originalMethod, swizzledMethod);
            }
        });
    }
    

    运用了runtime技术,在执行-(void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated时,执行- (void)setNavigationBarHidden:(BOOL)hidden animated:(BOOL)animated;,以此来解决滑动过程中,过渡不自然问题。

    该方法有一个不算缺陷的缺陷,就是一个工程只能只能置换一次。
    如果你在一个SDK中用到了该技术(修改类别名),并且另一个工程引入了该SDK,并且也使用了该技术。会造成滑动不自然。当然,你可以把该技术单独提出来,供SDK和工程共同引用,这样就可以解决问题了。

    方法三:

    通过文章刚开始介绍的UINavigationController组织图,可发现UINavigationController中只包含一个UINavigationBar。那么我们可以从UINavigationBar直接入手。

    self.edgesForExtendedLayout = UIRectEdgeTop;
    [self.navigationController.navigationBar setBackgroundImage:[UIImage new] forBarMetrics:UIBarMetricsDefault];
    if ([self.navigationController.navigationBar respondsToSelector:@selector(shadowImage)]) {
       [self.navigationController.navigationBar setShadowImage:[UIImage new]];
    }
    self.navigationController.navigationBar.backgroundColor = [UIColor clearColor];
    self.navigationController.navigationBar.alpha = 0.0;
    self.navigationController.navigationBar.backItem.hidesBackButton = YES;
    self.navigationController.navigationItem.hidesBackButton = YES;
    self.navigationItem.hidesBackButton = YES;
    

    该方法是直接控制UINavigationBar,使其背景图片、阴影图片、背景色、navigationItem等,以达到类似- (void)setNavigationBarHidden:(BOOL)hidden animated:(BOOL)animated;效果。
    常用于以下方法中

    - (void)viewWillAppear:(BOOL)animated; 
    - (void)viewDidAppear:(BOOL)animated; 
    - (void)viewWillDisappear:(BOOL)animated; 
    - (void)viewDidDisappear:(BOOL)animated;
    

    当然还有实现UINavigationControllerDelegate,在代理方法中通过判断showViewController类型,来控制显示。

    // Called when the navigation controller shows a new top view controller via a push, pop or setting of the view controller stack.
    - (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated;
    - (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated;
    

    这种方法好处是直接控制UINavigationBar,不好的地方是调用的方法过多,还要考虑viewControllers中的navigationItem。

    以上就是我整理的隐藏导航栏的三种方法。

    相关文章

      网友评论

        本文标题:iOS隐藏导航栏

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