一篇文章获取,statusBar,navigationBar,homeBar,tabBar 高度

4,047 阅读2分钟

iOS app 适配

1.背景介绍:iOS 画UI 经常需要需要取到statusBar,navigationBar,homeBar,tabBar 的高度。有时在UIViewController ,有时在UIView 中。所以我们不希望通过 self.navigationController..., self.tabBarController... 这种耦合度高的方式去取。 2.细想,OC 可以使用宏定义,swift 可以定义一个全局的布局Struct。本文章以swift 为例 3.看个实际中的高度,重点在于ipad 的statusBar的高度(都是模拟器)

模拟器设备型号设备系统版本statusBarnavigtionBartabBarhomeBarscreenWidthscreenheight
iphone5s12.120.044.049.00.0320.0568.0
iphoneXR12.144.044.083.035.0414.0896.0
iphoneX12.144.044.083.035.0375.0812.0
iphone12 Mini14.144.044.083.035.0375.0812.0
iphone12 PMax14.147.044.083.035.0428.0926.0
iphone12 Pro14.147.044.083.035.0390.0844.0
ipadP12.9-i-414.124.044.065.015.01024.01136.0
ipadP11-i-214.124.044.065.015.0834.01194.0
ipadAir-414.124.044.065.015.0820.01180.0
ipadAir-313.124.044.050.015.0834.01112.0
ipad-8th14.12044.050.015.0810.01080.0

实现:

  1. 先获取设备是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
*/