美文网首页
UINavigationBar 使用总结

UINavigationBar 使用总结

作者: YHWXQ简简单单的生活 | 来源:发表于2016-08-30 17:26 被阅读429次

    UINavigationBar是我们在开发过程中经常要用到的一个控件,下面是UINavigationBar一些常用的用法,部分代码我使用了OC和Swift书写

    1. 设置导航栏的标题
    self.navigationItem.title = @"UINavigationBar使用总结";
    

    注意:修改导航栏的字体大小和颜色

    self.navigationController?.navigationBar.titleTextAttributes = [NSForegroundColorAttributeName: UIColor.whiteColor(), NSFontAttributeName: UIFont.systemFontOfSize(24)]
    

    得到的效果如下:

    Paste_Image.png
    2. 设置导航栏的背景颜色-barTintColor
     self.navigationController.navigationBar.barTintColor = [UIColor redColor];
    

    得到的效果如下:

    barTintColor: 这个属性需要在iOS7以上才可以使用; 如果要支持iOS6以及以下的系统,可以参考这篇文章:UINavigationBar Background Color

    3. 设置导航栏的背景图片

    除了通过设置背景颜色来改变导航栏的外观外,我们还可以通过背景图片来设置导航栏的外观。

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

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

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

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

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

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

    • 在工程的Info.plist文件中添加一行UIViewControllerBasedStatusBarAppearance,选择Boolean类型,并设置为YES,Xcode会自动把名称变为View controller-based status bar appearance。

    • 在你的ViewController中添加下面的方法-(UIStatusBarStyle)preferredStatusBarStyle{ return UIStatusBarStyleLightContent;}

    想知道更多地方式,可以参考这两个页面:
    How to change Status Bar text color in iOS 7
    iOS7下Status Bar字体颜色修改
    特别需要注意的是,如果你的ViewController是通过navigationController push进来的,还需要加下面一句代码才能生效:

    self.navigationController.navigationBar.barStyle = UIBarStyleBlack;
    

    具体,可参考UIStatusBarStyle PreferredStatusBarStyle does not work on iOS 7

    我们来看看运行效果。

    5. 设置返回按钮的颜色-tintColor

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

    self.navigationController.navigationBar.tintColor = [UIColor whiteColor];
    

    得到的效果图如下:

    6. 设置返回按钮的图片
    // OC
    - (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;
    }
    // Swift: 我这个方法运行起来侧滑并没有失效
     func creatLeftBarbuttonItem() {
            let leftButtonFrame = CGRectMake(10, 10, 20, 25)
            let leftButton = UIButton(frame: leftButtonFrame)
            leftButton.setImage(UIImage(named: "fanhuijian"), forState: .Normal)
            leftButton.addTarget(self, action: #selector(self.leftButtonPop(_:)), forControlEvents: .TouchUpInside)
            self.navigationItem.leftBarButtonItem = UIBarButtonItem(customView: leftButton)
    }
        
    func leftButtonPop(sender: UIButton) {
            self.navigationController?.popViewControllerAnimated(true)
    }
    

    得到的效果如下:

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

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

    得到的效果如下:

    自定义返回按钮如果上面几种方式还无法满足你的要求(比如,需要同时设置返回按钮文字和图片),就需要用到UIBarButtonItem的initWithCustomView方法。

    - (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;}
    

    得到的效果图如下:

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

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

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

    • 设置导航栏的背景图(setBackgroundImage方法)
    • 设置导航栏的shadowImage (setShadowImage方法)
    // 方法一:
    // OC
    UINavigationBar *navigationBar = self.navigationController.navigationBar; 
    //设置透明的背景图,便于识别底部线条有没有被隐藏 
    [navigationBar setBackgroundImage:[[UIImage alloc] init] forBarPosition:UIBarPositionAny barMetrics:UIBarMetricsDefault];
     //此处使底部线条失效 
    [navigationBar setShadowImage:[UIImage new]];
    // Swift
     // 设置导航栏背景图片
       self.navigationController?.navigationBar.setBackgroundImage(UIImage(), forBarMetrics: UIBarMetrics.Default)
      // 设置导航栏阴影图片
      self.navigationController?.navigationBar.shadowImage = UIImage()
    
    // 方法二:
    // OC
    UINavigationBar *navigationBar = self.navigationController.navigationBar; 
    //设置透明的背景图,便于识别底部线条有没有被隐藏 
    [navigationBar setBackgroundImage:[[UIImage alloc] init] forBarPosition:UIBarPositionAny barMetrics:UIBarMetricsDefault];
     //此处使底部线条失效 
       self.navigationController!.navigationBar.clipsToBounds = YES;
    // Swift
     // 设置导航栏背景图片
       self.navigationController?.navigationBar.setBackgroundImage(UIImage(), forBarMetrics: UIBarMetrics.Default)
       self.navigationController!.navigationBar.clipsToBounds = true
    

    来看看效果图:

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

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

    有了上面的基础,设置导航栏线条的颜色就变得很简单了。
    首先,我做了个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]]];
    

    依照惯例,看下效果图:

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

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

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

    有下面两种方式可供选择,但是最终还是要用到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]; 
    }
    Swift
        override func viewDidLoad() {
            super.viewDidLoad()
            let closeItem = UIBarButtonItem(title: "关闭", style: .Plain, target: self, action: Selector("closeAction"))
            closeItem.tintColor = UIColor.whiteColor()
            //        self.navigationItem.leftItemsSupplementBackButton = true
            let leftButton = UIButton(type: .System)
            leftButton.backgroundColor = UIColor.clearColor()
            leftButton.frame = CGRectMake(0, 0, 45, 40)
            leftButton.setImage(UIImage(named: ""), forState: .Normal)
            leftButton.setTitle("返回", forState: .Normal)
            leftButton.tintColor = UIColor.whiteColor()
            leftButton.autoresizesSubviews = true
            leftButton.contentHorizontalAlignment = .Left
            leftButton.autoresizingMask = [.FlexibleWidth, .FlexibleLeftMargin]
            leftButton.addTarget(self, action: "goToBack", forControlEvents: .TouchUpInside)
            let backItem = UIBarButtonItem(customView: leftButton)
            navigationItem.leftBarButtonItems = [backItem, closeItem]  
        }
    

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

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

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

    这次,以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。

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

    全局设置导航栏的好处有两个:

    一是不用对每个NavigationBar进行设置;
    二是方便做主题管理,切换主题,只需要更改全局设置即可。
    
    13. 与导航栏相关的一些开源组件
    13.1 NJKWebViewProgress - 类似于Safiri加载网页时的进度显示
    13.2 FDFullscreenPopGesture - 一个丝滑的全屏滑动返回手势

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

    最后,奉上Demo的地址:NavigationBarDemo
    文/落羽生(简书作者)原文链接:http://www.jianshu.com/p/f0d3df54baa6

    相关文章

      网友评论

          本文标题:UINavigationBar 使用总结

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