前言

最近在项目开发的时候,发现项目提供的获取 「状态栏+导航栏高度」的方法,在 iPhone 12 系列机型上是错误的。解决了这个问题之后,决定做个简单的总结,于是有了这篇文章。

本文主要是分析了遇到的问题,比并提供了解决方案,最后总结了常用的准确获取 iPhone 状态栏、导航栏、TabBar高度的方法。如果只是被标题吸引进来的,可以直接跳到代码模版部分

文章目录

  • 前言
  • 1|问题归因
  • 2|利用系统方法获取状态栏高度
  • 3|代码模版
    • Objective-C 版本
    • Swift 版本
  • 参考文章

1|问题归因

问题出现的根源是,获取 「状态栏+导航栏高度」的方法采用的是类似于下面的判断是否为刘海屏,然后返回固定值的写法

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

现在早些时间,这种方法确实是没错的,但是在 iOS 14 系统之后,刘海屏手机的状态栏高度就不再统一是 44 了。下表是 iOS 15.2 上各刘海屏机型的状态栏高度,其中 iPhone 13 系列和 iPhone 12 系列是一致的,就不再重复列举。

机型 状态栏高度
iPhone XR/11 48
iPhone X/11 Pro/ 11 Pro Max/12 mini 44
iPhone 12/12 Pro/Pro Max 47

2|利用系统方法获取状态栏高度

因为上面那种写死的方法已经不能满足我们的需求了,于是我们采用系统的方法来获取。在 iOS 13.0 之前,我们可以通过 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;
}

3|代码模版

为了能正确获取系统顶部和底部相关元素(导航栏和安全区)的高度,这里提供了获取顶部和底部安全区、顶部状态栏和导航栏、底部 tabBar。

Objective-C 版本

UIDevice+VGAddition.h 中,对各方法进行了声明。

@interface UIDevice (VGAddition)/// 顶部安全区高度
+ (CGFloat)vg_safeDistanceTop;/// 底部安全区高度
+ (CGFloat)vg_safeDistanceBottom;/// 顶部状态栏高度(包括安全区)
+ (CGFloat)vg_statusBarHeight;/// 导航栏高度
+ (CGFloat)vg_navigationBarHeight;/// 状态栏+导航栏的高度
+ (CGFloat)vg_navigationFullHeight;/// 底部导航栏高度
+ (CGFloat)vg_tabBarHeight;/// 底部导航栏高度(包括安全区)
+ (CGFloat)vg_tabBarFullHeight;@end

UIDevice+VGAddition.m 中,对声明的各方法进行了实现。

#import "UIDevice+VGAddition.h"@implementation UIDevice (VGAddition)/// 顶部安全区高度
+ (CGFloat)vg_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)vg_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)vg_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)vg_navigationBarHeight {return 44.0f;
}/// 状态栏+导航栏的高度
+ (CGFloat)vg_navigationFullHeight {return [UIDevice vg_statusBarHeight] + [UIDevice vg_navigationBarHeight];
}/// 底部导航栏高度
+ (CGFloat)vg_tabBarHeight {return 49.0f;
}/// 底部导航栏高度(包括安全区)
+ (CGFloat)vg_tabBarFullHeight {return [UIDevice vg_tabBarHeight] + [UIDevice vg_safeDistanceBottom];
}@end

Swift 版本

UIDevice+VGAddition.swift

extension UIDevice {/// 顶部安全区高度static func vg_safeDistanceTop() -> CGFloat {if #available(iOS 13.0, *) {let scene = UIApplication.shared.connectedScenes.firstguard let windowScene = scene as? UIWindowScene else { return 0 }guard let window = windowScene.windows.first else { return 0 }return window.safeAreaInsets.top} else if #available(iOS 11.0, *) {guard let window = UIApplication.shared.windows.first else { return 0 }return window.safeAreaInsets.top}return 0;}/// 底部安全区高度static func vg_safeDistanceBottom() -> CGFloat {if #available(iOS 13.0, *) {let scene = UIApplication.shared.connectedScenes.firstguard let windowScene = scene as? UIWindowScene else { return 0 }guard let window = windowScene.windows.first else { return 0 }return window.safeAreaInsets.bottom} else if #available(iOS 11.0, *) {guard let window = UIApplication.shared.windows.first else { return 0 }return window.safeAreaInsets.bottom}return 0;}/// 顶部状态栏高度(包括安全区)static func vg_statusBarHeight() -> CGFloat {var statusBarHeight: CGFloat = 0if #available(iOS 13.0, *) {let scene = UIApplication.shared.connectedScenes.firstguard let windowScene = scene as? UIWindowScene else { return 0 }guard let statusBarManager = windowScene.statusBarManager else { return 0 }statusBarHeight = statusBarManager.statusBarFrame.height} else {statusBarHeight = UIApplication.shared.statusBarFrame.height}return statusBarHeight}/// 导航栏高度static func vg_navigationBarHeight() -> CGFloat {return 44.0}/// 状态栏+导航栏的高度static func vg_navigationFullHeight() -> CGFloat {return UIDevice.vg_statusBarHeight() + UIDevice.vg_navigationBarHeight()}/// 底部导航栏高度static func vg_tabBarHeight() -> CGFloat {return 49.0}/// 底部导航栏高度(包括安全区)static func vg_tabBarFullHeight() -> CGFloat {return UIDevice.vg_tabBarHeight() + UIDevice.vg_safeDistanceBottom()}
}

参考文章

  • https://blog.csdn.net/mlcldh/article/details/109474978

iOS 准确获取 iPhone 状态栏、导航栏、TabBar高度,看这篇就够了相关推荐

  1. 适配iOS 11和iPhone X——导航栏、UITableView

    每年的WWDC大会都激动和紧张好一段时间.激动的是期待苹果的新产品带来的那些黑科技,尤其今年的iPhone10周年纪念款iPhone X.紧张的当然是iOS.Swift和Xcode的升级,又要加班了( ...

  2. 反编译获取任何微信小程序源码——看这篇就够了(最新)

    一 准备工具 1 node.js 运行环境 下载地址:https://nodejs.org/en/ 2 反编译的脚本 链接:https://pan.baidu.com/s/1InxRoozDDb-C- ...

  3. uni-app小程序onShow执行两次;微信小程序onShow重复执行原因;导航栏tabBar页的onLoad函数不执行;App.vue页的onShow执行原因;onShow莫名其妙执行

    1.只有五种情况会触发导航栏tabBar页的onLoad函数,分别是: –1.1:首次进入到导航栏tabBar页面: –1.2:从微信分享进入的导航栏tabBar页面: –1.3:识别二维码跳转到小程 ...

  4. iOS适配iPhoneX/iphone11/iphone12 导航栏高度 (刘海屏幕)

    之前适配导航栏高度(刘海屏)是通过设备类型判断,判断设备为x.11或者12 之后,设置导航栏高度为88!但这样有一个缺点,就是要写好多设备类型代码且苹果出一个设备就得加一个判断-- 现在可以通过状态栏 ...

  5. MUI-设置沉浸式状态栏后MUI导航栏的高度问题

    上篇文章实现了沉浸式状态栏,如果不使用MUI的导航栏可以不用关心这个问题.由于我们的项目一开始被大量使用了MUI的导航栏,所以决定解决这个问题,不然就要对项目做大量的修改,时间成本太高. 问题描述与分 ...

  6. 小程序 底部导航栏(tabBar)图标的正确做法

    许多人都认为小程序系统的底部导航栏特别不好看,为了美观而选择自定义,从此身陷漩涡无法自拔.其实真正的原因是图标的图片处理不当(说白了就是前端和设计太菜了),导致会有线条变粗,间距不当的视觉感受. 除小 ...

  7. 前端 vue 自定义导航栏组件高度及返回箭头 自定义 tabbar 图标

    前端vue自定义导航栏组件高度及返回箭头 自定义tabbar图标, 下载完整代码请访问uni-app插件市场地址:https://ext.dcloud.net.cn/plugin?id=12986 喜 ...

  8. 手把手教你制作手机底部导航栏,领导看完都说好

    手把手教你制作手机底部导航栏,领导看完都说好

  9. Android获取顶部状态栏statusBar高度、底部导航栏navigationBar高度

    手机顶部显示时间.电量等信息的叫状态栏,即statusBar 有些手机比如华为在底部会有返回.回到主页面等虚拟功能键,这是导航栏,即navigationBar 下面列出一些项目中常用的功能代码? 嘻嘻 ...

最新文章

  1. HbuilderX中的git的使用 git HbuilderXgit HbuilderX 使用git
  2. 密码学专题 序列号文件
  3. JP摩根预测:诺基亚2017年净利润将达14.21亿美元
  4. 三只松鼠现“两只老鼠”:卖废纸箱发家致富??
  5. [目标检测]YOLO原理
  6. 向Spark集群提交任务
  7. 阿里“拆台”,中台真的不香了?
  8. Mac OS X10.11下CocoaPods的安装过程
  9. 工科数学分析寒假预习day4 更序问题和级数乘法
  10. 南大Lamda实验室俞扬:我的牛年小结
  11. Redis 与 Mysql 的数据一致性
  12. 单细胞转录组测序建库方法小结
  13. gRPC Name Resolution
  14. 利用 Python 实现简单的基于用户的商品推荐模型
  15. 笨方法学 python3怎么样_笨办法学python3日常问题解决
  16. 书单推荐2020-07-06
  17. c语言long型是什么,c语言long类型是什么意思
  18. 最新版CATIA,让您快速创造完整高级机械项目
  19. 网络安全与渗透:信息收集——google浏览器插件,代理服务(五)此生无悔入华夏,男儿何不带吴钩
  20. C# WPF 获取系统文化和国家信息(CultureInfo)类

热门文章

  1. .NET破解之PDFdo转换器
  2. 马云牵手微博做社交,会对微信构成威胁吗?
  3. 【项目实战】快来入门Groovy的基础语法吧
  4. Python使用Moviepy将图像序列转换为视频
  5. 2022-2028全球射频微针设备行业调研及趋势分析报告
  6. 聊聊找AI算法岗工作
  7. 关于软件测试从业者必备知识,录了几个视频
  8. Android 自动点击
  9. 车机开发问题: igo导航无audio focus机制导致声音焦点被抢走
  10. Python学习小组课程-课程大纲与Python开发环境安装