iOS导航栏设置

作者: Mr_LiTong | 来源:发表于2017-08-22 13:17 被阅读7608次

    作为一个iOS工程师,在项目中经常遇到需要设置导航栏的情况,有的时候是需要设置全局导航栏,有的时候需要单独的定义某个页面的导航栏。通过本篇文章,我们来讨论以下问题:

    • 导航栏遮挡的问题
    • 导航栏背景设置和分割线设置
    • 如何设置全局返回按钮
    • 如何控制导航栏的高度
    • 如何添加全局返回手势
    • 如何设置单个控制器的导航栏

    导航栏遮挡的问题

    iOS7后默认情况下,导航栏会遮挡ViewController的内容。这个原因是由于导航栏的半透明translucent属性造成的。(想要有半透明效果,那导航栏后边要有东西啊,要不然怎么看出来半透明效果)。知道原因那我们就知道该怎么修改了。将导航栏的translucent属性设为NO就可以了。

    [[UINavigationBar appearance] setTranslucent:NO];
    

    那除了这这种方法还有其他方法解决这个问题么?
    我又从UIViewController的接口文档中,我找到了一下API:

    @property(nonatomic,assign) UIRectEdge edgesForExtendedLayout NS_AVAILABLE_IOS(7_0); // Defaults to UIRectEdgeAll
    @property(nonatomic,assign) BOOL extendedLayoutIncludesOpaqueBars NS_AVAILABLE_IOS(7_0); // Defaults to NO, but bars are translucent by default on 7_0.  
    @property(nonatomic,assign) BOOL automaticallyAdjustsScrollViewInsets NS_AVAILABLE_IOS(7_0); // Defaults to YES
    

    从这些属性中我找到了其他办法。

    1. 我们将edgesForExtendedLayout的值设置为UIRectEdgeNone的时候,控制器视图的顶端会向下移动到导航栏的底部。这个属性和导航的translucent属性是没有关系的。这个属性只对子控制器有效,对容器控制器无效。
    2. extendedLayoutIncludesOpaqueBars从属性名称中我们可以看出这个属性是用来控制布局时是否包含透明Bar。这个属性是和NavBar和Tabbar的translucent属性是有关系的。这个属性只有当他们的translucent属性为NO时,这个属性才有用。当 extendedLayoutIncludesOpaqueBars = YES时。布局是从屏幕顶端(底部)开始的,会被导航栏(或TabBar)遮挡。当extendedLayoutIncludesOpaqueBars = NO时,布局是从导航栏底部(或TabBar顶部)开始的,不会被导航栏(或TabBar)遮挡。
    3. automaticallyAdjustsScrollViewInsets属性是用来控制容器视图控制器中的子控制器的可滚动区域插值的。例如当导航栏中的某个控制器视图是一个全屏UITableView,则会在UITableView的上下自动插入NavBar和Tabbar的的高度
    @interface UIViewController (UILayoutSupport)
    // These objects may be used as layout items in the NSLayoutConstraint API
    @property(nonatomic,readonly,strong) id<UILayoutSupport> topLayoutGuide NS_AVAILABLE_IOS(7_0);
    @property(nonatomic,readonly,strong) id<UILayoutSupport> bottomLayoutGuide NS_AVAILABLE_IOS(7_0);
    @end
    

    从接口文档中,我们得知这个用来做布局的。
    官方还给了一个例子:

    [button setTranslatesAutoresizingMaskIntoConstraints: NO];
    id topGuide = myViewController.topLayoutGuide;
    NSDictionary *viewsDictionary = NSDictionaryOfVariableBindings (button, topGuide);
    [myViewController.view addConstraints:
        [NSLayoutConstraint constraintsWithVisualFormat: @"V:[topGuide]-20-[button]"
                                                     options: 0
                                                     metrics: nil
                                                       views: viewsDictionary]];
    [self.view layoutSubviews]; // You must call this method here or the system raises an exception
    

    这两个属性是实现了<UILayoutSupport>协议的。从这个协议中我们可以得到length,也就是高度。这两个属性和NavBar和Tabbartranslucent属性是有关系的。只有当他们的translucent = YES时,他们的length才会返回对应的高度。否则length = 0

    导航栏背景设置和分割线设置

    导航栏背景
    1. 可以通过barTintColor来设置NavBar的颜色。
    @property(nullable, nonatomic,strong) UIColor *barTintColor NS_AVAILABLE_IOS(7_0) UI_APPEARANCE_SELECTOR;  // default is nil
    
    1. 可以通过背景图片来设置。
     - (void)setBackgroundImage:(nullable UIImage *)backgroundImage forBarMetrics:(UIBarMetrics)barMetrics NS_AVAILABLE_IOS(5_0) UI_APPEARANCE_SELECTOR;
    
    隐藏分割线(阴影线)
    @property(nullable, nonatomic,strong) UIImage *shadowImage NS_AVAILABLE_IOS(6_0) UI_APPEARANCE_SELECTOR;
    

    通过将shadowImage属性设为一个空的UIImage来实现隐藏分割线的效果。前提是导航栏的背景是用图片来设置的。当然还有其他方法,比如通过遍历NavBar的子视图来找到这个分割线,然后删除或隐藏,但我还是觉得这种方法是最简单快捷的。

    如何设置全局返回按钮

    设置返回按钮的图片
    [[UINavigationBar appearance] setBackIndicatorImage:baceImage];
     [[UINavigationBar appearance] setBackIndicatorTransitionMaskImage:baceImage];
    
    设置返回按钮的文字
    1. 方案一:继承UINavigationController
        //重写方法
        - (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated{
            [super pushViewController:viewController animated:animated];
            viewController.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc]initWithTitle:@"" style:(UIBarButtonItemStylePlain) target:nil action:nil];
        }
    
    1. 方案二:实现<UINavigationControllerDelegate>协议
     - (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated{
            viewController.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"" style:(UIBarButtonItemStylePlain) target:nil action:nil];
    }
    

    如何控制导航栏的高度

    添加UINavigationBarCategory重载sizeThatFits方法或者继承UINavigationBar重写sizeThatFits属性。

    - (CGSize)sizeThatFits:(CGSize)size{
        
        return (CGSize){
            [UIScreen mainScreen].bounds.size.width,70
        };
    }
    

    如何添加全局返回手势

    一个丝滑的全屏滑动返回手势
    FDFullscreenPopGesture
    这个库不用一行代码就可以给UINavigationController添加了全屏滑动返回手势。并且非常完美的实现了指定控制器导航栏隐藏的问题。可以对指定控制器隐藏导航栏和关闭全屏滑动返回手势。

    如何设置单个控制器的导航栏

    利用FDFullscreenPopGesture,隐藏指控制器的导航栏,然后添加自定义的导航栏,来完成我们想要的效果,比如滑动动画隐藏或其他效果。

    相关文章

      网友评论

        本文标题:iOS导航栏设置

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