前言
最近在iPhone 12 系列机型上开发项目时,发现使用项目提供的获取状态栏、导航栏高度方法获取到的高度是错误的,随后跟踪排查最终解决这个问题,所以自己想简单的总结一下问题原因和解决办法。
本文主要介绍问题原因和解决办法,最终提供一个能准确获取iPhone 状态栏、导航栏、TabBar高度的方法。
问题原因
出现问题的原因是,我们大多开发在使用获取状态栏、导航栏高度方法都是以下方法来获取的:
// 状态栏高度,iPhoneX 是判断是否为刘海屏
#define StatusBar_Height (isIPhoneX ? 44.0f : 20.0f)
在iOS 14系统以前,使用这种方法获取是没有问题的,但是在之后,刘海屏的手机状态栏高度就不在是统一的44px咯,根据下表我们看一看目前iOS 15系统上的各机型的状态栏高度:
机型 | 状态栏高度 |
---|---|
iPhone XR/11 | 48px |
iPhone X/11 Pro/ 11 Pro Max/12 mini | 44px |
iPhone 12/12 Pro/Pro Max | 47px |
使用系统方法获取状态栏高度
可以看出使用上面方法已经不在满足我们的开发需求了,于是我就想到使用系统提供的方法来获取,通过 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+S
tateHeight
.h
中,声明各方法名称:文章来源:https://www.toymoban.com/news/detail-442292.html
@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+S
tateHeight
.m
中实现各方法进行。文章来源地址https://www.toymoban.com/news/detail-442292.html
#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
到了这里,关于最全最准确获取iOS 状态栏、导航栏、TabBar高度的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!