關於iPhone X 的適配
1.屏幕尺寸相關變化
- 高度增加了145pt,變成812pt.
- 屏幕圓角顯示,註意至少留10pt邊距。
- 狀態欄高度由20pt變成44pt,留意這個距離就能避開“劉海”的尷尬,相應的導航欄以上變化64->88。
- 底部工具欄需要為home indicator留出34pt邊距。
- 物理分辨率為1125px * 2436px.
2.橫豎屏安全區對比
3.其他設備安全區域對比
4.應用設計
5.控件布局
更多可查看官方文檔和視頻Creating apps for iPhone X.
如何讓APP適配?
APP啟動樣式適配
相信有一部分道友的APP在iPhone X上運行時並沒有像想象中那樣占滿整個屏幕, 而是保持著原有的高度 在屏幕中心位置, 針對這個問題 目前經過實驗得出可以通過以下方式使APP按照全屏模式運行:
- 通過
LaunchScreen.storyboard
方式啟動 - 如果使用的是Assets中的LaunchImage, 在增加了iPhone X尺寸的圖片配置後.
LaunchScreen.storyboard
方式不用多說, 這裏說一下如何在LaunchImage中增加iPhone X尺寸的圖片配置.
準備一張尺寸:1125 * 2436的啟動圖片, 移動到LaunchImage的Finder目錄中, 並在LaunchImage中的Contents.json
文件中增加 (註意Json格式):
{ "extent" : "full-screen", "idiom" : "iphone", "subtype" : "2436h", "filename" : "圖片名.png", "minimum-system-version" : "11.0", "orientation" : "portrait", "scale" : "3x" }
按照以上方式配置就完全解決了這個問題.
APP內部樣式適配
iOS11為UIViewController
和UIView
增加了兩個新的屬性safeAreaInsets
和safeAreaLayoutGuide
, 通過這兩個屬性我們可以獲得安全區域的範圍, 通過上圖可以很清楚的看到安全區域的範圍, 我們要做的是讓那些不能被遮擋的內容和控件在安全區域範圍內顯示, 註意!這句話非常重要.
safeAreaInsets
適用於手動計算.safeAreaLayoutGuide
適用於自動布局.
Frame布局方式適配示例
一般來說 可以通過在原有視圖坐標計算時加入安全區域的範圍值, 下面舉個例子:
一個APP 它的NavigationBar使用的是自定義的UIView
UINavigationBar
, 這個自定義的UIView
的frame
屬性為CGRectMake(0, 0, 375, 64)
.這樣的
UIView
在其他設備上是沒有問題的, 標準的導航欄尺寸, 但是如果運行在iPhone X上 你會發現看上去無比的別扭, 因為異形屏幕會造成部分顯示內容的遮擋問題, 這時候就要用到安全區域這個概念來解決這一問題.
先說一說通常自定義導航欄的結構, 高度是為64
由44
高度的導航欄內容區域和20
高度的狀態欄區域(電池條那部分 status bar)組成, 44
高度的導航欄內容區域用來顯示導航欄上的控件, 如返回按鈕 標題視圖等等, 現在, 在iPhone X上, 原來的狀態欄(status bar)高度不再考慮了, 取而代之的是安全區域頂部間距safeAreaInsets.top
, 我們將原有的結構改為 安全區域頂部距離屏幕的距離safeAreaInsets.top
+ 導航欄內容區域44
, 這樣完成了一個自定義導航欄視圖在iPhone X上的適配.
下面是適配前後的效果對比:
再來看一下適配後的自定義導航欄視圖的UI結構
這只是舉一個簡單的例子, 因為不同的應用設計都是不同的, 但是適配的思路都是一樣的, 還是那句話 我們要做的是讓那些不能被遮擋的內容和控件在安全區域範圍內顯示, 在計算布局時 將安全區域這個新特性考慮進去, iPhone X的適配也不是難事.
說一下在代碼中的安全區域的適配該如何去寫:
iOS11 為UIViewController
和UIView
增加了一個新的方法 - (void)viewSafeAreaInsetsDidChange;
這個方法如名字一樣 在安全區域改變後會被調用, 我們可以在需要適配的UIViewController
和UIView
中重寫這個方法, 並且在這個方法中來根據safeAreaInsets
屬性更新子視圖控件的布局位置.
這裏有一點要註意的是當UIViewController
調用- (void)viewDidLoad
時它的所有子視圖的safeAreaInsets
屬性都等於UIEdgeInsetsZero
, 也就是說在- (void)viewSafeAreaInsetsDidChange;
方法調用前 是無法通過當前視圖控制器的子視圖獲取到safeAreaInsets
的, 不過獲取當前window對象的safeAreaInsets
屬性用來計算也是可以的, 但是不建議這麽做, 一個視圖控制器的子視圖的處理當然要以它所在的控制器為準.
- (void)viewSafeAreaInsetsDidChange
在UIViewController
中第一次調用的時間是在- (void)viewWillAppear:(BOOL)animated
調用之後, 在- (void)viewWillLayoutSubviews
調用之前.
當然如果你要改變一個UIViewController
的safeAreaInsets
值, 可以通過設置addtionalSafeAreaInsets
屬性來實現, 例如你要自定義一些特殊的樣式時.
如果你改變了一個UIViewController
的safeAreaInsets
屬性值, - (void)viewSafeAreaInsetsDidChange
也會被調用.
另外, 給道友們的分享一個獲取某View安全區域範圍的宏
#define VIEWSAFEAREAINSETS(view) ({UIEdgeInsets i; if(@available(iOS 11.0, *)) {i = view.safeAreaInsets;} else {i = UIEdgeInsetsZero;} i;})
使用起來比較簡潔
VIEWSAFEAREAINSETS(view).left
VIEWSAFEAREAINSETS(self.view).right
AutoLayout布局方式示例
iOS11以前,我們布局時, 視圖的 top
和 bottom
一般參照的是 Top Layout Guide
和 Bottom Layout Guide
.
iOS11以後, 那兩個參照已經 deprecated
(過時)了, 而是被Safe Area
所取代.
參考自官方文檔
關於iPhone X 的適配