天天看點

iPhoneX(劉海屏)适配

iPhoneX(劉海屏)适配

在 iOS11的時候,蘋果破天荒釋出了一款新螢幕樣式的手機,俗稱劉海屏。世人皆道醜,而後紛紛買之。自此,iOS 開發者們也走向了 iPhoneX系列的适配之旅。

差別

狀态欄,導航欄的改變和底部 Home Indicator的新增 。

普通螢幕 iPhoneX(劉海屏)系列
狀态欄高度 20 44
導航欄高度 64 88
tabBar 49 83(其中有34Home Indicator互動區)

導航欄實際内容展示高度還是44,隻是狀态欄變高。

使用系統原生的導航欄、tabbar系統會自動适配。自定義的都需要手動适配X。比如隐藏了導航欄,使用自定義View代替導航欄的時候,你就需要手動适配(打碼判斷或者參考 SafeArea添加限制)。

iOS 11也引入了安全區域 SafeArea 的概念,以便我們适配和布局參考。

底層View添加限制的時候減少以superView為參考,使用Safe area為限制布局依據,這樣就不用關注是否為劉海屏。

除了這些,還有鍵盤高度的增加等。

判斷 iPhoneX 系列

有部分小夥伴是通過擷取螢幕寬高各版本裝置尺寸來判斷,但是這樣的弊端是,每增加一次裝置都有可能需要添加,非常不推薦。而是應該用 keyWindow 的 SafeArea.bottom來判斷。

Swift

extension UIDevice {
    /// 是否為 IphoneX (劉海屏)系列
    static var isIphoneXSeries: Bool {
        var keyWindow = UIApplication.shared.keyWindow
        if #available(iOS 13, *), keyWindow == nil {
            keyWindow = UIApplication.shared.windows.first
        }
        if #available(iOS 11.0, *), UIDevice().userInterfaceIdiom == .phone {
            if let key = keyWindow, key.safeAreaInsets.bottom > 0 { // 不能判斷 top(普通螢幕為20, 劉海屏為44),而且還要考慮螢幕旋轉問題。
                return true
            }
        }
        return false
    }
}
           

Objective-C

宏定義

#define kIS_iPhoneX_Series ({BOOL isPhoneX = NO;\
if (@available(iOS 13.0, *)) {\
    isPhoneX =  [UIApplication sharedApplication].windows.firstObject.safeAreaInsets.bottom > 0.0;\
    }\
else if (@available(iOS 11.0, *)) {\
    isPhoneX = [[UIApplication sharedApplication] delegate].window.safeAreaInsets.bottom > 0.0;\
}\
(isPhoneX);}) 
           

其他

Objective-C

相關宏定義

#define kNavBar_Content_Height 44.0f  
#define kStatusBar_Height (kIS_iPhoneX_Series==YES)?44.0f: 20.0f
#define kNavBar_Height (kIS_iPhoneX_Series==YES)?88.0f: 64.0f
#define kTabBar_Height (kIS_iPhoneX_Series==YES)?83.0f: 49.0f
           

Home Indicator 的影藏

針對某些界面,也許我們希望全界面顯示,影藏Inducator

這時候需要重寫ViewController中的如下方法:

// 重寫 控制home indicator的影藏
// 沒有互動兩秒後影藏
-(BOOL)prefersHomeIndicatorAutoHidden{
    return YES;
}
           

Xib适配iPhoneX(相容 iOS11 之前版本)

iOS11版本以上

如果是基于iOS11适配X,你隻需要将限制基準參考Safe Area,就可以解決大部分導航欄和底部欄的适配。

iOS11版本以前

你就需要以SuperView為基準的輔助限制,否則還是會導緻被狀态欄擋住的問題。

綜合解決:

  1. 添加兩條限制
  2. Safe Area為基準的限制 優先級 小于 以Super View的。
  3. 将SuperView為基準的限制關系設定為大于等于【如下圖】。

添加一個UIView作為自定義導航欄。

iPhoneX(劉海屏)适配

[外鍊圖檔轉存失敗,源站可能有防盜鍊機制,建議将圖檔儲存下來直接上傳(img-vWmNTRY4-1604631069553)(data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)]

同樣的方法也可以适配底部導航欄或視圖。

适配效果圖

iPhoneX(劉海屏)适配

[外鍊圖檔轉存失敗,源站可能有防盜鍊機制,建議将圖檔儲存下來直接上傳(img-PI6xaoQz-1604631069554)(data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)]

Storyboard裡面隻需要添加以SafeArea為基礎的限制即可。

參考:Safe area layout guides in xib files - iOS 10 --stackOverflow

​ iOS 11 safe area layout guide backwards compatibility --stackOverflow

擴充:準确擷取iPhone裝置型号

詳細推薦參考:适配iOS11與iPhoneX