UINavigationBar 使用总结

作者: lexiaoyao20 | 来源:发表于2015-09-12 01:18 被阅读40014次

    UINavigationBar是我们在开发过程中经常要用到的一个控件,下面我会为大家介绍一些常用的用法。

    1. 设置导航栏的标题

    这个不多说,直接上代码
    self.navigationItem.title = @"UINavigationBar使用总结";

    2. 设置导航栏的背景颜色

    //通过barTintColor来设置背景色
     self.navigationController.navigationBar.barTintColor = [UIColor redColor];```
    得到的效果如下:
    
    ![Snip20150912_1.png](http:https://img.haomeiwen.com/i452998/97239749e8c4d721.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
    > barTintColor: 这个属性需要在iOS7以上才可以使用; 如果要支持iOS6以及以下的系统,可以参考这篇文章:[UINavigationBar Background Color ](http://www.saturngod.net/articles/uinavigationbar-background-color/)
    
    ## 3. 设置导航栏的背景图片
    除了通过设置背景颜色来改变导航栏的外观外,我们还可以通过背景图片来设置导航栏的外观。
    

    [self.navigationController.navigationBar setBackgroundImage:[UIImage imageNamed:@"Background"]
    forBarMetrics:UIBarMetricsDefault];```

    Snip20150912_2.png

    在这里得稍微说说UIBarMetrics这个枚举, 它主要是用来控制在不同状态下导航栏的显示。和UIButton的
    - (void)setBackgroundImage:(nullable UIImage *)image forState:(UIControlState)state 这个方法有点类似。

    //表示横屏竖屏都显示
    UIBarMetricsDefault,
    //表示在只横屏下才显示,和UIBarMetricsLandscapePhone功效一样,不过iOS8已经弃用了
    UIBarMetricsCompact,
    UIBarMetricsDefaultPrompt和UIBarMetricsCompactPrompt这两个我还没搞清楚是什么意思,有知道的朋友不妨给我们来普及一下。。

    4. 更改顶部状态栏的颜色

    从效果图可以看出,我们设置背景色或者背景图之后,状态栏依然还是默认的黑色,这样感觉不好看。好在,系统给我们提供了UIStatusBarStyleDefaultUIStatusBarStyleLightContent两种样式供我们选择。

    • UIStatusBarStyleDefault,系统的默认样式,黑色内容,用于浅色的背景(如白色)
    • UIStatusBarStyleLightContent 白色内容,用于深色的背景(如红色)

    下面来看看具体怎么实现,主流的实现方式是分两步:

    1. 在工程的Info.plist文件中添加一行UIViewControllerBasedStatusBarAppearance,选择Boolean类型,并设置为YES,Xcode会自动把名称变为View controller-based status bar appearance。
      Snip20150913_4.png
    2. 在你的ViewController中添加下面的方法
    -(UIStatusBarStyle)preferredStatusBarStyle{
        return UIStatusBarStyleLightContent;
    }
    

    想知道更多地方式,可以参考这两个页面:How to change Status Bar text color in iOS 7iOS7下Status Bar字体颜色修改

    另外,特别需要注意的是,如果你的ViewController是通过navigationController push进来的,还需要加下面一句代码才能生效:
    self.navigationController.navigationBar.barStyle = UIBarStyleBlack;
    具体,可参考UIStatusBarStyle PreferredStatusBarStyle does not work on iOS 7

    恩,我们来看看运行效果。

    Snip20150913_5.png

    5. 设置返回按钮

    从上面的效果图中我们可以看到返回按钮还是默认的蓝色按钮,下面我将会大家来介绍返回按钮的个性化。

    • 设置返回按钮的颜色
      只需要设置tintColor属性即可
    self.navigationController.navigationBar.tintColor = [UIColor whiteColor];
    

    得到的效果图如下:


    Snip20150915_1.png
    • 只设置返回按钮的图片
    - (void)goToBack {
        [self.navigationController popViewControllerAnimated:YES];
    }
    
    - (void)setBackButtonWithImage {
        UIImage *leftButtonIcon = [[UIImage imageNamed:@"LeftButton_back_Icon"]
                                   imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
        UIBarButtonItem *leftButton = [[UIBarButtonItem alloc] initWithImage:leftButtonIcon
                                                                       style:UIBarButtonItemStyleBordered
                                                                      target:self
                                                                      action:@selector(goToBack)];
        self.navigationItem.leftBarButtonItem = leftButton;
        
        //修复navigationController侧滑关闭失效的问题
        self.navigationController.interactivePopGestureRecognizer.delegate = (id)self;
    }
    

    得到的效果如下:


    Snip20150915_2.png

    这里需要注意的地方有三点:

    1. 需要自己实现返回按钮的事件。
    2. 特别的解释下UIImage的imageWithRenderingMode:方法,参数UIImageRenderingModeAlwaysOriginal 表示总是用原图渲染,如果不这么设置,返回按钮将会显示tintColor的颜色(默认为蓝色)。UITabbarItem也存在同样地问题。
    3. 我们自己设置返回按钮,会导致系统的侧滑关闭效果失效。添加上面代码中最后一句代码即可修复。
    • 仅设置返回按钮的文字
    - (void)setBackButtonTitle {
        UIBarButtonItem *leftButton = [[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(@"取消", nil)
                                                                       style:UIBarButtonItemStylePlain
                                                                      target:self action:@selector(goToBack)];
        leftButton.tintColor = [UIColor whiteColor];
        self.navigationItem.leftBarButtonItem = leftButton;
    }
    

    得到的效果如下:

    Snip20150915_3.png
    • 自定义返回按钮
      如果上面几种方式还无法满足你的要求(比如,需要同时设置返回按钮文字和图片),就需要用到UIBarButtonIteminitWithCustomView方法。
    - (void)setCustomLeftButton {
        UIView* leftButtonView = [[UIView alloc]initWithFrame:CGRectMake(0, 0, 60, 40)];
        UIButton* leftButton = [UIButton buttonWithType:UIButtonTypeSystem];
        leftButton.backgroundColor = [UIColor clearColor];
        leftButton.frame = leftButtonView.frame;
        [leftButton setImage:[UIImage imageNamed:@"LeftButton_back_Icon"] forState:UIControlStateNormal];
        [leftButton setTitle:@"返回" forState:UIControlStateNormal];
        leftButton.tintColor = [UIColor redColor];
        leftButton.autoresizesSubviews = YES;
        leftButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;
        leftButton.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleLeftMargin;
        [leftButton addTarget:self action:@selector(goToBack) forControlEvents:UIControlEventTouchUpInside];
        [leftButtonView addSubview:leftButton];
        UIBarButtonItem* leftBarButton = [[UIBarButtonItem alloc] initWithCustomView:leftButtonView];
        self.navigationItem.leftBarButtonItem = leftBarButton;
    }
    

    得到的效果图如下:

    Snip20150915_5.png

    设置rightBarButtonItem基本上脱离不了上面的几种方式,大家可以参照上面返回按钮的设置方式。

    6. 隐藏导航栏底部的线条

    有时候遇到一些特殊的要求,需要隐藏导航栏底部的线条。
    两行代码就可以做到。

    • 设置导航栏的背景图(setBackgroundImage方法)
    • 设置导航栏的shadowImage (setShadowImage方法)
    UINavigationBar *navigationBar = self.navigationController.navigationBar;
        //设置透明的背景图,便于识别底部线条有没有被隐藏
        [navigationBar setBackgroundImage:[[UIImage alloc] init]
                           forBarPosition:UIBarPositionAny
                               barMetrics:UIBarMetricsDefault];
        //此处使底部线条失效
        [navigationBar setShadowImage:[UIImage new]];
    

    来看看效果图:

    Snip20150922_1.png

    另外,还有一种做法,一行代码就可以达到效果,也真是够神奇的。。

    //方法二:
        self.navigationController.navigationBar.clipsToBounds = YES; 
    

    想要知道更详细的内容可以参考这个页面:How to hide iOS7 UINavigationBar 1px bottom line

    7. 设置导航条底部线条的颜色

    有了上面的基础,设置导航栏线条的颜色就变得很简单了。
    首先,我做了个UIImage的分类:通过颜色转成UIImage;
    然后,用上面的方案来设置导航栏底部线条。

    颜色转图片的代码:

    @implementation UIImage (ColorImage)
    
    + (UIImage *)imageWithColor:(UIColor *)color
    {
        CGRect rect = CGRectMake(0.0f, 0.0f, 1.0f, 1.0f);
        UIGraphicsBeginImageContext(rect.size);
        CGContextRef context = UIGraphicsGetCurrentContext();
        
        CGContextSetFillColorWithColor(context, [color CGColor]);
        CGContextFillRect(context, rect);
        
        UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
        
        return image;
    }
    
    @end
    

    设置导航栏底部线条颜色的代码:

    UINavigationBar *navigationBar = self.navigationController.navigationBar;
        [navigationBar setBackgroundImage:[[UIImage alloc] init]
                           forBarPosition:UIBarPositionAny
                               barMetrics:UIBarMetricsDefault];
        //此处使底部线条颜色为红色
        [navigationBar setShadowImage:[UIImage imageWithColor:[UIColor redColor]]];
    

    依照惯例,看下效果图:

    Snip20150923_2.png

    当然还有其他的方式也可以做到,如addSubview, addSubLayer等。感兴趣的话可以参考下这个页面:iOS7 - Change UINavigationBar border color

    8. 在导航栏上添加多个按钮

    以微信打开网页时的效果为例,效果图如下,有两个按钮:返回和关闭。

    微信效果图.png
    有下面两种方式可供选择,但是最终还是要用到leftBarButtonItems这个方法。
    #define UserMethod1 0
        
        UIBarButtonItem *closeItem = [[UIBarButtonItem alloc] initWithTitle:@"关闭" style:UIBarButtonItemStylePlain target:self action:@selector(closeAction)];
        if (UserMethod1) {
            //方法一:
            self.navigationItem.leftBarButtonItems = @[closeItem];
            //要求显示默认的返回按钮,但是文字会显示默认的Back,暂时还不知道这个文字怎么改
            self.navigationItem.leftItemsSupplementBackButton = YES;
        }
        else {
            //方法二
            UIButton* leftButton = [UIButton buttonWithType:UIButtonTypeSystem];
            leftButton.backgroundColor = [UIColor clearColor];
            leftButton.frame = CGRectMake(0, 0, 45, 40);
            [leftButton setImage:[UIImage imageNamed:@"LeftButton_back_Icon"] forState:UIControlStateNormal];
            [leftButton setTitle:@"返回" forState:UIControlStateNormal];
            leftButton.tintColor = [UIColor whiteColor];
            leftButton.autoresizesSubviews = YES;
            leftButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;
            leftButton.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleLeftMargin;
            [leftButton addTarget:self action:@selector(goToBack) forControlEvents:UIControlEventTouchUpInside];
            UIBarButtonItem* backItem = [[UIBarButtonItem alloc] initWithCustomView:leftButton];
            
            self.navigationItem.leftBarButtonItems = @[backItem,closeItem];
        }
    

    然后,运行的效果图如下:

    在导航栏上添加多个按钮.png

    方法一用到了leftItemsSupplementBackButton 这个属性,会显示系统默认的返回按钮,但是文字也是显示默认的Back文字,目前还没找到怎么修改这个文字,如果有谁知道,还请不吝赐教;所以我暂时还是建议大家用方法二。相应的还有 rightBarButtonItems 这个属性,如果要在导航栏右侧展示多个按钮的话,可以设置这个属性。

    9. 在导航栏上添加分段控件

    这次,以QQ为例,代码如下:

    UISegmentedControl *segControl = [[UISegmentedControl alloc] initWithItems:@[@"消息",@"电话"]];
        segControl.tintColor = [UIColor colorWithRed:0.07 green:0.72 blue:0.96 alpha:1];
        [segControl setSelectedSegmentIndex:0];
        self.navigationItem.titleView = segControl;
    

    代码很简单,就是设置titleView这个属性,当然,你也可以把这个属性设置为你自定义的View。

    类似于QQ的导航栏.png

    10. 导航栏全局属性设置

    //全局设置导航栏主题
    - (void)setNavigationControllerAppearance {
        [UINavigationBar appearance].barStyle  = UIBarStyleBlack;
        [[UINavigationBar appearance] setBarTintColor:[UIColor colorWithWhite:0.1 alpha:0.5]];
        [[UINavigationBar appearance] setTintColor:[UIColor whiteColor]];
    }
    

    全局设置导航栏的好处有两个:一是不用对每个NavigationBar进行设置;二是方便做主题管理,切换主题,只需要更改全局设置即可。

    11. 与导航栏相关的一些开源组件

    11.1 NJKWebViewProgress - 类似于Safiri加载网页时的进度显示

    网页加载进度.png网页加载进度.png

    11.2 FDFullscreenPopGesture - 一个丝滑的全屏滑动返回手势

    对应的文章介绍可以点这个链接

    丝滑的全屏返回手势.png丝滑的全屏返回手势.png

    最后,奉上Demo的地址:NavigationBarDemo

    相关文章

      网友评论

      • 随行的羊:希望关注 “iOS开发知识小集” 专题,学习更精炼的iOS技术 😄 https://www.jianshu.com/c/7c8c0fe15550
      • 神一样的男人卫:老铁我给你双击6666
      • goyohol:图片设置了,跳转到其他页面后, 设置状态栏颜色没影响,设置导航栏有问题! 模糊的!
        用view Hierarchy看是backgroundImage挡在前面

        -(void)viewWillDisappear:(BOOL)animated { }里设置:
        [self.navigationController.navigationBar setBackgroundImage:nil forBarMetrics:UIBarMetricsDefault];
        不管用。。。。。
      • First灬DKS:博主你好:为什么自定义的返回按钮相比原生自带的返回按钮,位置靠右了一些?这个问题有没有好的解决方法呢?
        First灬DKS:@落羽生 好的,非常感谢
        lexiaoyao20:@First灬DKS 可以这样来解决,比如向左移动5个像素:

        UIImage *leftBarImage = [[UIImage imageNamed:@"BackIcon"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
        UIBarButtonItem *leftButton = nil;
        leftButton = [[UIBarButtonItem alloc] initWithImage:leftBarImage
        style:UIBarButtonItemStylePlain
        target:self action:@selector(leftBarItemTouched:)];
        leftButton.imageInsets = UIEdgeInsetsMake(0, -5, 0, 0);
        self.navigationItem.leftBarButtonItem = leftButton;
      • Waisti:👏
      • ca2d4fbee6f1:你的问题:方法一用到了leftItemsSupplementBackButton 这个属性,会显示系统默认的返回按钮,但是文字也是显示默认的Back文字,目前还没找到怎么修改这个文字,如果有谁知道,还请不吝赐教 我的答案:在上一界面写下: UIBarButtonItem *backItem = [[UIBarButtonItem alloc] initWithTitle:@"返回"
        style:UIBarButtonItemStyleDone
        target:nil
        action:nil];
        self.navigationItem.backBarButtonItem = backItem; 那个Back就会被修改
      • iYeso:牛:blush:
        很喜欢
        lexiaoyao20:@小2的客栈 过奖了:stuck_out_tongue_winking_eye:
      • 外星派来拯救coder的鼓励师:在没有title的页面,加一个backBarButtonItem,就可以控制back这个返回的文字了。
        由于刚学swift,代码是swift:
        let backbtn = UIBarButtonItem(title: "取消", style: UIBarButtonItemStyle.Plain, target:self, action: nil)
        self.navigationItem.backBarButtonItem = backbtn
      • 34ab9b9838b1:Mark,iOS导航栏
      • 利尔德:挺全的呀
      • 独木舟的木:8.在导航栏上添加多个按钮,方法二是把系统的返回按钮替换掉了,要自己实现返回方法。用方法一可以这么写:

        // 设置导航栏返回按钮
        UIBarButtonItem *backBarButtonItem = [[UIBarButtonItem alloc]
        initWithTitle:@"返回"
        style:UIBarButtonItemStylePlain
        target:self
        action:nil];
        self.navigationItem.backBarButtonItem = backBarButtonItem;
        // 设置导航栏其他按钮
        UIBarButtonItem *closeBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"关闭" style:UIBarButtonItemStylePlain target:self action:@selector(backToRootViewController)];
        self.navigationItem.leftBarButtonItem = closeBarButtonItem;
        // 设置左侧自定义按钮是否与返回按钮共同存在
        self.navigationItem.leftItemsSupplementBackButton = YES;
        lexiaoyao20:@独木舟的木 :+1:受教了
      • 打南边来了个辣妈:感谢作者。希望更多好作品
      • 王大吉Rock:这个很厉害,学习了。:clap:
      • 郑明明:更改文字颜色呢
        郑明明:@落羽生 好的嘿嘿
        lexiaoyao20:@NtZheng 里面都有介绍的,你也可以下载Demo看看
      • 勿问情殇:楼主,我想问下,我设的背景色,跟你的蓝色那种一样,颜色感觉被弱化了,怎么解决。
        lexiaoyao20:@勿问情殇 默认情况下,NavigationBar是有个模糊透明的效果的,你可以设置 myNavigationBar.translucent = NO 来禁用透明效果。
      • 十一岁的加重:很透彻啊,还有这么多图
      • PPAbner:没有细看,但good!!!
      • Eason_Gao:不错
      • 大王叫我来巡山_Cong:你好 我想问 我想通过button的点击方法改变导航栏的背景颜色 通过这个方法貌似没用 self.navigationController.navigationBar.barTintColor = [UIColor redColor];
        大王叫我来巡山_Cong:@落羽生 我知道什么原因了 因为我用通知的原因 谢谢
        lexiaoyao20:@大王叫我来巡山_Cong 估计得看看你的完整代码才知道是怎么回事了,我这边Demo是没有问题的,你可以参考下:https://github.com/lexiaoyao20/NavigationBarDemo
      • 李前途:总结到位
      • 3d908e62289f:很不错啊。。期待之后的介绍啊
        lexiaoyao20:@山竹肥牛 谢谢关注,最近我太懒了,这个星期内把坑填上
      • brownfeng:非常棒!!
        lexiaoyao20:@酱油PP的ios小站 谢谢!

      本文标题:UINavigationBar 使用总结

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