iOS开发之status bar

作者: helloDolin | 来源:发表于2016-03-09 13:43 被阅读992次

    iOS开发中,我们经常遇到改变状态栏的情况(显示不显示,白底黑字,黑底白字等等)

    第一种处理方式

    由UIApplication处理,一种比较暴力的方式去处理
    打开项目的.plist文件

    上面的这种格式是苹果默认的格式,看着不是很爽,我更喜欢下面的这种方式打开,当然也可以以XML方式打开,看个人爱好了,添加UIViewControllerBasedStatusBarAppearance这个key,value赋值为NO,字面意思:状态栏的显示不基于UIViewController,也就是说ViewController没有改变状态栏的权利

    好的,准备工作已经做好了,直接上源码:
    感兴趣的可以直接粘贴复制跑一下

    //
    //  TestViewController.m
    //  status_bar_test
    //
    //  Created by shaolin on 16/3/9.
    //  Copyright © 2016年 shaolin. All rights reserved.
    //
    
    #import "FirstViewController.h"
    
    @interface FirstViewController ()
    
    @property (nonatomic,strong)UIButton* btn;
    
    @end
    
    @implementation FirstViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        self.title = @"status bar test";
        self.view.backgroundColor = [UIColor orangeColor];
        [self.view addSubview:self.btn];
    }
    
    - (UIButton*)btn {
        if (!_btn) {
            _btn = [UIButton buttonWithType:UIButtonTypeSystem];
            _btn.frame = CGRectMake(0, 64, 375, 100);
            _btn.backgroundColor = [UIColor grayColor];
            [_btn setTitle:@"test" forState:UIControlStateNormal];
            [_btn addTarget:self action:@selector(test) forControlEvents:UIControlEventTouchUpInside];
        }
        return _btn;
    }
    
    - (void)test {
        static BOOL b = YES;
        if (b) {
            [UIApplication sharedApplication].statusBarStyle = UIStatusBarStyleLightContent;
        } else {
            [UIApplication sharedApplication].statusBarStyle = UIStatusBarStyleDefault;
        }
        b = !b;
    }
    
    @end
    

    statusBarStyle,苹果提供了四个枚举


    但是,我给其赋值的时候看到了这样的情况:


    很显然下面的两个枚举苹果已经不建议使用了

    控制status bar是否显示

    [UIApplication sharedApplication].statusBarHidden = YES;
    

    请注意

    上面所有的操作都是基于sharedApplication的,所以修改后即为全局修改,如果只想在某个ViewController使用,又想用这种暴力的方式,那就需要在VC生命周期的最后将其改变回来


    第二种处理方式

    status bar显示控制权交给ViewController


    #import "FirstViewController.h"
    
    @interface FirstViewController ()
    
    @end
    
    @implementation FirstViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        self.view.backgroundColor = [UIColor orangeColor];
    }
    
    - (BOOL)prefersStatusBarHidden {
        return NO;
    }
    
    - (UIStatusBarStyle)preferredStatusBarStyle {
        return UIStatusBarStyleLightContent;
    }
    
    @end
    

    运行结果:

    运行结果

    请注意

    当我们的VC(ViewController的简称)是基于UINavigationController这种形式的时候,这种处理方式只能控制status bar显示不显示,并不能控制其style,亲测,如下代码:

    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
        FirstViewController* vc = [FirstViewController new];
        UINavigationController* navVc = [[UINavigationController alloc]initWithRootViewController:vc];
        self.window.rootViewController = navVc;
        return YES;
    }
    
    //
    //  status_bar_test
    //
    //  Created by shaolin on 16/3/9.
    //  Copyright © 2016年 shaolin. All rights reserved.
    //
    
    #import "FirstViewController.h"
    
    static BOOL b = NO;
    
    @interface FirstViewController ()
    
    @property (nonatomic,strong)UIButton* btn;
    
    @end
    
    @implementation FirstViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        self.title = @"status bar test";
        self.view.backgroundColor = [UIColor orangeColor];
        [self.view addSubview:self.btn];
    }
    
    - (UIButton*)btn {
        if (!_btn) {
            _btn = [UIButton buttonWithType:UIButtonTypeSystem];
            _btn.frame = CGRectMake(0, 64, 375, 100);
            _btn.backgroundColor = [UIColor grayColor];
            [_btn setTitle:@"test" forState:UIControlStateNormal];
            [_btn addTarget:self action:@selector(test) forControlEvents:UIControlEventTouchUpInside];
        }
        return _btn;
    }
    
    - (UIStatusBarAnimation)preferredStatusBarUpdateAnimation {
        return UIStatusBarAnimationFade;
    }
    
    - (BOOL)prefersStatusBarHidden {
        return b;
    }
    
    //- (UIStatusBarStyle)preferredStatusBarStyle {
    //    if (b) {
    //        return UIStatusBarStyleLightContent;
    //    }
    //    return UIStatusBarStyleDefault;
    //}
    
    - (void)test {
        b = !b;
        //这个方法会通知系统去调用当前UIViewController的**preferredStatusBarStyle**方法
        [self setNeedsStatusBarAppearanceUpdate];
    }
    
    @end
    

    那这种情况下怎么去控制呢?
    解决方案:

    1. 自定义一个UINavigationController
    2. 重写 - (UIViewController *)childViewControllerForStatusBarStyle 方法
    #import "MyNavController.h"
    
    @interface MyNavController ()
    
    @end
    
    @implementation MyNavController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        
    }
    /**
     *  默认返回值为nil。
     *  当我们调用setNeedsStatusBarAppearanceUpdate时,系统会调用application.window的rootViewController的preferredStatusBarStyle
     *  方法
     *  我们的程序里一般都是用UINavigationController做root,如果是这种情况,那我们自己的UIViewController里的preferredStatusBarStyle根本不会被调用
     *  这个时候不要调用我自己(就是UINavigationController)的preferredStatusBarStyle方法,而是去调用navigationController.topViewController的preferredStatusBarStyle方法
     *
     *  @return stack最上层的vc,我们知道navigation是以stack的形式跳转的
     */
    - (UIViewController *)childViewControllerForStatusBarStyle {
        return self.topViewController;
    }
    @end
    

    AppDelegate.m文件,用自定义的NavigationController作为window的rootViewController

    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
        FirstViewController* vc = [FirstViewController new];
        MyNavController* navVc = [[MyNavController alloc]initWithRootViewController:vc];
        self.window.rootViewController = navVc;
        return YES;
    }
    

    效果图:

    效果图.gif

    附上GitHib源码地址:
    status_bar_test


    如果两种方式同时在项目中怎么办?

    取info.plist中 UIViewControllerBasedStatusBarAppearance中的设置:

    NSNumber *isVCBasedStatusBarAppearanceNum = [[NSBundle mainBundle]objectForInfoDictionaryKey:@"UIViewControllerBasedStatusBarAppearance"];
    

    设为YES时isVCBasedStatusBarAppearanceNum值为1
    设为NO时isVCBasedStatusBarAppearanceNum值为0
    根据这个去处理你的逻辑哈


    希望会给大家带来帮助O(∩_∩)O

    相关文章

      网友评论

      本文标题:iOS开发之status bar

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