前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >iOS小技能:设置状态栏背景颜色(图片)

iOS小技能:设置状态栏背景颜色(图片)

作者头像
公众号iOS逆向
发布2022-08-22 11:29:50
1.9K0
发布2022-08-22 11:29:50
举报
文章被收录于专栏:iOS逆向与安全

引言

  1. 设置状态栏背景颜色的解决方案:

使用新的API 【statusBarManager】

  1. 通过安全区域高度判断是否IphoneX之后的机型:if ([UIApplication sharedApplication].delegate.window.safeAreaInsets.bottom > 0)

I 状态栏背景颜色的适配方案

  • 问题
代码语言:javascript
复制
 [Bugly]  Trapped uncaught exception 'NSInternalInconsistencyException', reason: 'App called -statusBar or -statusBarWindow on UIApplication: this code must be changed as there's no longer a status bar or status bar window. Use the statusBarManager object on the window scene instead.' 
  • 旧代码
代码语言:javascript
复制
    UIView *statusBar = [[[UIApplication sharedApplication] valueForKey:@"statusBarWindow"] valueForKey:@"statusBar"];

1.1 使用新的API 【statusBarManager】

  • 解决方案:使用keyWindow.windowScene.statusBarManager
代码语言:javascript
复制
if (@available(iOS 13.0, *)) {
       UIView *statusBar = [[UIView alloc]initWithFrame:[UIApplication sharedApplication].keyWindow.windowScene.statusBarManager.statusBarFrame] ;
        statusBar.backgroundColor = color;
        [[UIApplication sharedApplication].keyWindow addSubview:statusBar];
    } else {
        // Fallback on earlier versions
        UIView *statusBar = [[[UIApplication sharedApplication] valueForKey:@"statusBarWindow"] valueForKey:@"statusBar"];
           if ([statusBar respondsToSelector:@selector(setBackgroundColor:)]) {
               statusBar.backgroundColor = color;
           }
    }


statusBarFrame

代码语言:javascript
复制
            CGRect rectStatus = [[UIApplication sharedApplication] statusBarFrame];
            //API_DEPRECATED("Use the statusBarManager property of the window scene instead.", ios(2.0, 13.0));
            

           if (@available(iOS 13.0, *)) {

               rectStatus = [UIApplication sharedApplication].keyWindow.windowScene.statusBarManager.statusBarFrame;
               
       }

1.2 适配特色场景:状态是有透明或者半透明的效果的场景

  • 补充:如果整个项目的状态栏(电池栏)都是有颜色的,并且都是不透明的,上面这个方法完全可以应付。但是如果有状态是有透明或者半透明的效果,上面这个方法还是不能胜任,越透明越明显;经过一番查找,终于发现问题:
  • 问题:

1、iOS 13之前,可以通过valueForKey 获取UIApplication的statusBar,因为UIApplication是单例,因此,在iOS 12,通过: [[[UIApplication sharedApplication] valueForKey:@"statusBarWindow"] valueForKey:@"statusBar"]拿到的statusBar永远是同一个对象。2、iOS 13之后,因为苹果不允许使用KVC的valueForKey访问私有属性。通过上面的代码获取statusBar时,发现每次每次获取都调用 alloc:init的方法,重新生成一个statusBar;然后添加到UIApplication的keyWindow上,再设置背景颜色。因此这个方法多次调用就会创建多份statusBar,造成内存开销不说,想设置状态栏为为透明,根本没效果。

解决办法:既然定位到问题所在,办法就是保证iOS 13 之后,每次也都能拿到有去只有一个对象。方法有很多,我的方法代码如下:使用 static 配合 gcd

代码语言:javascript
复制
HSSingletonM(QCTStatusBarTool);

+ (void)setStatusBarBackgroundColor4ios13:(UIColor *)color {
    
    static UIView *statusBar = nil;
    static dispatch_once_t onceToken;
    if (@available(iOS 13.0, *)) {  //iOS 13不允许使用valueForKey、setValue: forKey获取和设置私有属性;
        dispatch_once(&onceToken, ^{
            statusBar = [[UIView alloc] initWithFrame:[UIApplication sharedApplication].statusBarFrame];
            [[UIApplication sharedApplication].keyWindow addSubview:statusBar];
        });
                
     } else {
         statusBar = [[[UIApplication sharedApplication] valueForKey:@"statusBarWindow"] valueForKey:@"statusBar"];
    }
    if ([statusBar respondsToSelector:@selector(setBackgroundColor:)]) {
        statusBar.backgroundColor = color;
    }
}


II 通过安全区域高度判断是否IphoneX之后的机型

代码语言:javascript
复制
#define isIphoneX [QCT_Common isiPhoneX]

+ (BOOL)isiPhoneX {
    

        if (@available(iOS 11.0, *)) {
            if ([UIApplication sharedApplication].delegate.window.safeAreaInsets.bottom > 0) {//iphoneX横屏
                 return  YES;
                
            } else {
                return  NO;
                
            }
            
        } else {
            
            return NO;
        }
    
    

}


代码语言:javascript
复制

///*状态栏和导航栏总高度*/
#define kStatusBarHeight (CGFloat)(isIphoneX?(88.0):(64.0))
/*iPhoneX的状态栏高度差值*/
#define kPtatusBarHeight (CGFloat)(isIphoneX?(24.0):(0))
/*底部安全区域远离高度*/
#define kDtatusBarHeight (CGFloat)(isIphoneX?(34.0):(0))


2.1 应用场景1:自定义导航栏内容

导航栏显示公告和标题

代码语言:javascript
复制
    navView = [[UIImageView alloc]initWithFrame:CGRectMake(0, 0, kWidth, kStatusBarHeight)];

2.2 应用场景2:设置状态栏背景图片

代码语言:javascript
复制

/**
 用于设置状态栏的背景图片
 */
@property (weak, nonatomic) UIButton *imgLable;

- (UIButton *)imgLable{
    if (nil == _imgLable) {
        UIButton *tmpView = [[UIButton alloc]init];
        _imgLable = tmpView;
        
        tmpView.userInteractionEnabled = NO;
        [tmpView setBackgroundImage:[UIImage imageNamed:@"img_daiban_topbg_top"] forState:UIControlStateNormal];
                

    
        [self addSubview:_imgLable];
        __weak __typeof__(self) weakSelf = self;
        
        [_imgLable mas_makeConstraints:^(MASConstraintMaker *make) {
            make.left.right.equalTo(weakSelf).offset(0);
            
            make.top.equalTo(weakSelf).offset(0);
            make.height.mas_equalTo(kStatusBarHeight);
//            make.top.equalTo.offset(kAdjustRatio(44));
        }];


    }
    return _imgLable;
}



推荐使用自动布局,和使用API获取高度

代码语言:javascript
复制

#define kstatusBarH [[UIApplication sharedApplication] statusBarFrame].size.height


#define knavHeight  self.navigationController.navigationBar.frame.size.height


//获取状态栏的高度
CGFloat statusHeight = [[UIApplication sharedApplication] statusBarFrame].size.height;
NSLog(@"状态栏高度:%f",statusHeight);

//获取导航栏的高度
CGFloat navHeight = self.navigationController.navigationBar.frame.size.height;
NSLog(@"导航栏高度:%f",navHeight);

//获取tabBar的高度
//1.在tabBarController中使用(你的继承自UITabBarController的VC)
CGFloat tabBarHeight = self.tabBar.frame.size.height;
NSLog(@"tabBar高度:%f",tabBarHeight);
//2.在非tabBarController中使用
UITabBarController *tabBarVC = [[UITabBarController alloc] init];//(这儿取你当前tabBarVC的实例)
CGFloat tabBarHeight = tabBarVC.tabBar.frame.size.height;
NSLog(@"tabBar高度:%f",tabBarHeight);

see also

  • iOS13适配暗黑模式方案:1、设置app不支持Dark Mode 2、制定深色模式开发规范 https://blog.csdn.net/z929118967/article/details/104293041
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-07-02,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 iOS逆向 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 引言
  • I 状态栏背景颜色的适配方案
    • 1.1 使用新的API 【statusBarManager】
      • 1.2 适配特色场景:状态是有透明或者半透明的效果的场景
      • II 通过安全区域高度判断是否IphoneX之后的机型
        • 2.1 应用场景1:自定义导航栏内容
          • 2.2 应用场景2:设置状态栏背景图片
          • see also
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档