iOS app 适配
1.背景介绍:iOS 画UI 经常需要需要取到statusBar,navigationBar,homeBar,tabBar 的高度。有时在UIViewController ,有时在UIView 中。所以我们不希望通过 self.navigationController..., self.tabBarController... 这种耦合度高的方式去取。 2.细想,OC 可以使用宏定义,swift 可以定义一个全局的布局Struct。本文章以swift 为例 3.看个实际中的高度,重点在于ipad 的statusBar的高度(都是模拟器)
模拟器设备型号 | 设备系统版本 | statusBar | navigtionBar | tabBar | homeBar | screenWidth | screenheight |
---|---|---|---|---|---|---|---|
iphone5s | 12.1 | 20.0 | 44.0 | 49.0 | 0.0 | 320.0 | 568.0 |
iphoneXR | 12.1 | 44.0 | 44.0 | 83.0 | 35.0 | 414.0 | 896.0 |
iphoneX | 12.1 | 44.0 | 44.0 | 83.0 | 35.0 | 375.0 | 812.0 |
iphone12 Mini | 14.1 | 44.0 | 44.0 | 83.0 | 35.0 | 375.0 | 812.0 |
iphone12 PMax | 14.1 | 47.0 | 44.0 | 83.0 | 35.0 | 428.0 | 926.0 |
iphone12 Pro | 14.1 | 47.0 | 44.0 | 83.0 | 35.0 | 390.0 | 844.0 |
ipadP12.9-i-4 | 14.1 | 24.0 | 44.0 | 65.0 | 15.0 | 1024.0 | 1136.0 |
ipadP11-i-2 | 14.1 | 24.0 | 44.0 | 65.0 | 15.0 | 834.0 | 1194.0 |
ipadAir-4 | 14.1 | 24.0 | 44.0 | 65.0 | 15.0 | 820.0 | 1180.0 |
ipadAir-3 | 13.1 | 24.0 | 44.0 | 50.0 | 15.0 | 834.0 | 1112.0 |
ipad-8th | 14.1 | 20 | 44.0 | 50.0 | 15.0 | 810.0 | 1080.0 |
实现:
- 先获取设备是iphone,还是ipad
import UIKit
import CoreTelephony
import AuthenticationServices
struct AppAndDeviceInfo {
#warning("error")
/// 设备是否是iphone, 模拟器不可用
/// - Returns: description
static func deviceIsiPhone() -> Bool {
var systemInfo = utsname()
uname(&systemInfo)
let machineMirror = Mirror(reflecting: systemInfo.machine)
let identifier = machineMirror.children.reduce("") { identifier, element in
guard let value = element.value as? Int8, value != 0 else { return identifier }
return identifier + String(UnicodeScalar(UInt8(value)))
}
//模拟器x86-64
return identifier.contains("iPhone")
}
/**************************************/
{
static let screenSize: CGSize = UIScreen.main.bounds.size
static let screenWidth: CGFloat = screenSize.width
static let screenHeigth: CGFloat = screenSize.height
static var statusBarHeight: CGFloat {
if #available(iOS 13.0, *) {
let statusManager = UIApplication.shared.windows.first?.windowScene?.statusBarManager
return statusManager?.statusBarFrame.height ?? 20.0
} else {
return UIApplication.shared.statusBarFrame.height
}
}
static var navigationBarHeight: CGFloat {
return 44.0
}
static var navigationBarMaxY: CGFloat {
return 44 + statusBarHeight;
}
static var homeBarHeight: CGFloat {
var height: CGFloat = 0
if AppAndDeviceInfo.deviceIsiPhone() {
if statusBarHeight >= 44 { //刘海屏幕手机,有homeBar
height = 34
}else {
height = 0
}
return height
}
if AppAndDeviceInfo.deviceIsiPad() {
if tabBarHeight >= 51 {
height = 15.0
}else {
height = 0.0
}
}
return height
}
/// method 1. 先取tabBar 获取到高度,直接新建的tabBarContrller 无法获取正确高度,
static var tabBarHeight: CGFloat { // include homeBar
//此处为提高内聚性,显的些许麻烦。(读者可以设置改属性为存储属性,在delegate 中赋值,然后再使用)
guard let tabVC: UITabBarController = UIApplication.shared.keyWindow?.rootViewController as? UITabBarController else {
return getTabbarheightByDeviceInfo()
}
return tabVC.tabBar.frame.size.height
}
/// method 2. 可以在设置UITabBarController 后,对其赋值,然后使用
static var storedTabBarHeight:CGFloat?
/// method 3. 对于未来设备,判断可能出错 & ipad同一设备不同iOS 版本高度也会不同
/// - Returns: description
static func getTabbarheightByDeviceInfo() -> CGFloat {
if AppAndDeviceInfo.deviceIsiPhone() {
if statusBarHeight > 21.0 {
return 83
}
return 0.0
}else if AppAndDeviceInfo.deviceIsiPad() {
if statusBarHeight > 23.0 {
return 65.0 // 实际情况下,可能为 50,或者65
}else {
return 50.0
}
}else {
return 0.0
}
}
}
/*
demo 地址:https://github.com/gree180160/BarItemHeight.git
*/