irpas技术客

最全最准确获取iOS 状态栏、导航栏、TabBar高度_chenshilinaaa_ios statusbarmanager

网络 1770

前言

最近在iPhone 12 系列机型上开发项目时,发现使用项目提供的获取状态栏、导航栏高度方法获取到的高度是错误的,随后跟踪排查最终解决这个问题,所以自己想简单的总结一下问题原因和解决办法。

本文主要介绍问题原因和解决办法,最终提供一个能准确获取iPhone 状态栏、导航栏、TabBar高度的方法。

问题原因

出现问题的原因是,我们大多开发在使用获取状态栏、导航栏高度方法都是以下方法来获取的:

// 状态栏高度,iPhoneX 是判断是否为刘海屏 #define StatusBar_Height (isIPhoneX ? 44.0f : 20.0f)

在iOS 14系统以前,使用这种方法获取是没有问题的,但是在之后,刘海屏的手机状态栏高度就不在是统一的44px咯,根据下表我们看一看目前iOS 15系统上的各机型的状态栏高度:

机型状态栏高度iPhone XR/1148pxiPhone X/11 Pro/ 11 Pro Max/12 mini44pxiPhone 12/12 Pro/Pro Max47px
使用系统方法获取状态栏高度

可以看出使用上面方法已经不在满足我们的开发需求了,于是我就想到使用系统提供的方法来获取,通过?UIApplication?单例中的?statusBarFrame?属性获取状态状态栏改度:

[UIApplication sharedApplication].statusBarFrame.size.height;

我发现 iOS 13.0系统 之后,UIApplication?单例中的?statusBarFrame?属性被废弃了。不建议使用了,系统希望我们使用?UIStatusBarManager?类中的?statusBarFrame?来进行获取:

if (@available(iOS 13.0, *)) { NSSet *set = [UIApplication sharedApplication].connectedScenes; UIWindowScene *windowScene = [set anyObject]; UIStatusBarManager *statusBarManager = windowScene.statusBarManager; return statusBarManager.statusBarFrame.size.height; } 代码模块

为了统一和方便快速获取系统顶部和底部安全区、顶部状态栏和导航栏、底部 tabBar,我将新建一个分类来实现这些方法,方便项目全局引用:

在?UIDevice+StateHeight.h?中,声明各方法名称:

@interface UIDevice () /** 顶部安全区高度 **/ + (CGFloat)dev_safeDistanceTop; /** 底部安全区高度 **/ + (CGFloat)dev_safeDistanceBottom; /** 顶部状态栏高度(包括安全区) **/ + (CGFloat)dev_statusBarHeight; /** 导航栏高度 **/ + (CGFloat)dev_navigationBarHeight; /** 状态栏+导航栏的高度 **/ + (CGFloat)dev_navigationFullHeight; /** 底部导航栏高度 **/ + (CGFloat)dev_tabBarHeight; /** 底部导航栏高度(包括安全区) **/ + (CGFloat)dev_tabBarFullHeight; @end

在?UIDevice+StateHeight.m?中实现各方法进行。

#import "UIDevice+StateHeight.h" @implementation UIDevice () // 顶部安全区高度 + (CGFloat)dev_safeDistanceTop { if (@available(iOS 13.0, *)) { NSSet *set = [UIApplication sharedApplication].connectedScenes; UIWindowScene *windowScene = [set anyObject]; UIWindow *window = windowScene.windows.firstObject; return window.safeAreaInsets.top; } else if (@available(iOS 11.0, *)) { UIWindow *window = [UIApplication sharedApplication].windows.firstObject; return window.safeAreaInsets.top; } return 0; } // 底部安全区高度 + (CGFloat)dev_safeDistanceBottom { if (@available(iOS 13.0, *)) { NSSet *set = [UIApplication sharedApplication].connectedScenes; UIWindowScene *windowScene = [set anyObject]; UIWindow *window = windowScene.windows.firstObject; return window.safeAreaInsets.bottom; } else if (@available(iOS 11.0, *)) { UIWindow *window = [UIApplication sharedApplication].windows.firstObject; return window.safeAreaInsets.bottom; } return 0; } //顶部状态栏高度(包括安全区) + (CGFloat)dev_statusBarHeight { if (@available(iOS 13.0, *)) { NSSet *set = [UIApplication sharedApplication].connectedScenes; UIWindowScene *windowScene = [set anyObject]; UIStatusBarManager *statusBarManager = windowScene.statusBarManager; return statusBarManager.statusBarFrame.size.height; } else { return [UIApplication sharedApplication].statusBarFrame.size.height; } } // 导航栏高度 + (CGFloat)dev_navigationBarHeight { return 44.0f; } // 状态栏+导航栏的高度 + (CGFloat)dev_navigationFullHeight { return [UIDevice vg_statusBarHeight] + [UIDevice vg_navigationBarHeight]; } // 底部导航栏高度 + (CGFloat)dev_tabBarHeight { return 49.0f; } // 底部导航栏高度(包括安全区) + (CGFloat)dev_tabBarFullHeight { return [UIDevice vg_statusBarHeight] + [UIDevice vg_safeDistanceBottom]; } @end


1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,会注明原创字样,如未注明都非原创,如有侵权请联系删除!;3.作者投稿可能会经我们编辑修改或补充;4.本站不提供任何储存功能只提供收集或者投稿人的网盘链接。

标签: #iOS