蘋果公司于2017年9月13日凌晨發布了兩款新的手機—— iPhon 8與iPhone X,作為全新的屏幕樣式 iPhone X 的適配問題也成了大家都很關注的一個問題。
以下通過官方文檔、項目中出現的問題、網上的資料來談談 iPhone X 的適配
一、官方文檔說明
布局
1、在 iPhone X 上預覽你的應用。你可以 Simulator(Xcode 附屬應用 )來預覽你的應用。請注意檢查應用元素是否被屏幕切割、布局是否正常等。對于一些新特性,比如廣色域顯示,使用實體設備才能起到最好的預覽效果。
2、為了更好的提供全屏使用體驗。 確保背景能夠延伸到屏幕邊緣,垂直滾動布局,如表單或集合頁需一直延續至屏幕底部。(親測使用系統提供的標準組件沒有問題)
3、插入必要內容以防止被裁切。一般來說,內容應該是居中對稱的,這樣在任何方向上都能獲得比較好的觀感,也不會被屏幕圓角、傳感器區域和主屏幕支持器所影響。為了保證最佳效果,請使用系統提供的標準控件和響應式布局來構建您的頁面。所有的應用都應該遵循 UIKit 定義的安全區域和布局邊距,這些區域可以根據設備的上下文進行適當的填充。同時,安全區可以防止你的內容覆蓋狀態欄、導航欄、工具欄和標簽欄。
4、注意狀態欄的高度。iPhone X 的狀態欄比其他 iPhone 上要更高一些。如果您的應用元素尺寸是根據狀態欄高度來判斷,或是元素位置處于狀態欄下方,則必須更新您的應用,請跟據用戶的設備來動態定位內容。請注意,當后臺任務(如錄音和位置跟蹤)處于活動狀態時,iPhone X上的狀態欄不會改變高度。
5、如果您的應用目前是隱藏狀態欄,請根據 iPhone X 屏幕特點重新考慮。iPhone X 的屏幕比 4.7 英寸 iPhone 的屏幕高很多,省去狀態欄占據的內容區域可能并不會得到很好的利用。狀態欄還展示了人們覺得有用的一些信息,請思考當你將它隱藏時換來的價值要高于顯示。
6、在重復使用現有圖稿時,請注意長寬比差異。iPhone X 與常規 iPhone 的屏幕長寬比不同,因此,全屏的 4.7 寸屏圖像在 iPhone X 上會出現裁切或適配寬度顯示。同理 iPhone X 的圖片在 4.7 寸屏上也會出現此情況。所以,重要的視覺稿請根據設備型號做相應的調整。
7、避免將可交互控件放在屏幕底部和角落。屏幕底部可以通過手勢進入主屏幕和多任務頁面,這些手勢可能會覆蓋您在此區域中實現的自定義手勢。屏幕角落可能無法讓人們舒適地觸達。
8、不要遮蓋或引導關注屏幕新特性的關鍵位置。不要使用放置黑色欄在屏幕上下區域等方式來試圖隱藏設備的圓角、傳感器區域和主頁指示器,也不要使用類似括號、輪廓、形狀和教學文案等視覺元素來引導用戶關注這些區域。
9、允許自動隱藏回到主屏幕指示器。當自動隱藏開啟時,用戶幾秒鐘不觸碰屏幕指示器便會漸隱消失。用戶觸碰屏幕后指示器再次顯示。此特性只能用于沉浸式預覽樣式,比如視頻播放或幻燈片樣式。
10、在橫屏狀態下官方給出的錯誤的設計樣式和正確的設計樣式
二、****iPhone X 屏幕變化總結
1、屏幕尺寸
5.15 英寸 458 ppi(ppi : 每英寸所擁有的像素(pixel)數目)
1125px × 2436px(75pt × 812pt @3x)
為了更好的突出 iPhone X 的屏幕顯示效果,請使用 3 倍圖
2、iPhone 7 和 iPhone X 對比:
如下圖所示,iPhone 7 設備渲染后分辨率為 750 x 1334,邏輯分辨率只有 375 x 667。iPhone X 設備渲染后分辨率為 1125 x 2436,邏輯分辨率是為 375 x 812。可以看出顯示區域寬度是相同的,但是高度多了 145pt
3、頂部多出傳感器區域(俗稱劉海),底部的實體 home 鍵消失,屏幕下方多出返回主頁指示器(網上有稱之為 homeBar 的,官方沒有明確命名,為了方便表達,以下內容稱之為 homeBar)屏幕四個角變成大圓角。官方文檔上表明:在你為 iPhone X 設計界面時,請必須保證所有設計內容不能被屏幕圓角、上方傳感器區域、下方返回主頁指示器所遮擋。
4、statusBar 的高度在 iPhone X 上變成了 44,其他設備都是 20。對于開發者來說,項目中隱藏導航欄,偏移量按照原來的 20 固定值來使用的,在屏幕上出現偏移。(對于 App 混合開發的項目,iOS 開發在開發中使用動態獲取的值進行計算,前端開發的同學適配的時候可以通過獲取手機型號來賦值)
5、tabBar 的高度在 iPhone X 上變成了 83,其他設備是 49,多出 34,多出的部分是給 homeBar 流出控件,可以算出 homeBar 的高度為 34。
三、適配**** iPhone X****的新特性
1、顏色
iPhone X 屏幕支持 P3 色彩空間,這意味著它將可以顯示更多的色彩,比 sRGB 要更加艷麗。
使用廣色域來提高視覺體驗。使用了廣色域的圖片和視頻會更加生動,使用廣色域的數據圖表和狀態指示器會更加有沖擊力。更多信息請查看「色彩管理」。
2、手勢
iPhone X 使用屏幕邊緣手勢來訪問主屏幕、應用切換、通知中心和控制用心。
避免干擾到系統級別的屏幕邊緣手勢。人們使用這些手勢來使用所有應用,在極少數情況下,像游戲這樣的沉浸式應用程序可能需要自定義的屏幕邊緣手勢。優先于系統的手勢:第一次滑動會調用自定義手勢,而第二次滑動則會調用系統手勢。這種自定義行為(稱為邊緣保護)應該謹慎使用,因為它使得用戶難以訪問系統級的操作。更多信息請查看「手勢」。
3、Face ID
iPhone X 支持 Face ID 進行身份驗證。如果您的應用程序與 Apple Pay 或其他系統身份驗證功能集成,請勿在 iPhone X 上引用 Touch ID。同樣,請不要在支持 Touch ID 的設備上引用Face ID。更多信息請查看「驗證」。
4、鍵盤功能
在 iPhone X 上,Emoji、語言切換和語音識別按鈕會自動顯示在鍵盤的下方(即使使用自定義鍵盤)。 您的應用程序不能影響這些按鈕,為了避免造成困擾,請不要在鍵盤中重復定義這些按鈕。
四、對于原有的項目,適配**** iPhone X ****可能會遇到的問題
1、App 頁面沒有完全充滿屏幕
原因:
UIScreen的初始化是根據我們進入的第一個頁面去進行參數化的
解決方式:
補上1125 x 2436的圖或采用 LaunchScreen.xib 或者 LaunchScreen.storyboard 進行配置啟動圖
2、下拉刷新被頭部劉海遮蓋
原因:
頭部劉海遮蓋住了刷新控件
解決:
增加刷新控件的高度
3、個人中心界面頭部導航欄問題
原因:
沒有使用系統的導航欄,自定義的導航欄導致高度增大
解決方式:
動態獲取導航欄高度作為自定義的導航欄高度
4、底部的按鈕和 homeBar 重合
原因:
status 的高度改變,造成按鈕和 Home 鍵重合
解決:
動態計算 frame 的值
(歡迎補充)
五、關于**** iOS11 ****新增新特性**** safeArea ****對項目造成的影響
在iOS11設備上運行出現最多問題應該就是 tableview 莫名奇妙的偏移 20pt 或者 64pt,原因就是iOS11棄用了 automaticallyAdjustsScrollViewInsets 屬性,新增了 UIScrollView 的 contentInsetAdjustmentBehavior 屬性,根本原因就是 iOS11 新引入的 safeArea 引起(個人認為這是 iPhone X 屏幕的大浮動變動引起的,為了 view 不被 statusBar、navigationBar、tabBar 遮住,更好的適配 iPhone X)
什么是安全區域呢?
如下圖,藍色區域為安全區域。系統認為 statusBar、navigationBar、tabBar 之外的區域為安全區域,對于 UIScrollView、UITableView、UICollectionView,系統會自動給他添加一個內邊距,造成偏移。即使把 navigationBar 設為透明,系統也認為安全區域是從 navigationbar 的 bottom 開始的。
比如:當你的APP中使用的是自定義的 navigationbar,隱藏掉系統的navigationbar,并且 tableView 的 frame 為 (0,0,SCREEN_WIDTH, SCREEN_HEIGHT) 開始,那么系統會自動調整SafeAreaInsets值為 (STATUS_BAR_HEIGHT,0,0,0),如果使用了系統的 navigationbar,那么 SafeAreaInsets 值為 (64,0,0,0),如果也使用了系統的 tabbar,那么 SafeAreaInsets 值為 (STATUS_BAR_HEIGHT + NAVI_BAR_HEIGHT, 0, TAB_BAR_HEIGHT, 0)。(SCREEN_WIDTH 表示屏幕寬,SCREEN_HEIGHT 表示屏幕高,STATUS_BAR_HEIGHT 表示狀態欄高度,NAVI_BAR_HEIGHT 表示導航欄高度,TAB_BAR_HEIGHT 表示底部選項卡高度)
官方定義:安全區域定義了view中可視區域的部分,保證不被系統的狀態欄、或父視圖提供的 view 如導航欄覆蓋。
當項目中出現莫名偏移的情況,可參考的解決方法:
1、根據取代 automaticallyAdjustsScrollViewInsets 屬性的 contentInsetAdjustmentBehavior 屬性
if (@available(iOS 11.0, *)) {
self.webView.scrollView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
// 設置內邊距
self.webView.scrollView.contentInset = UIEdgeInsetsMake(0, 0, 0, 0);
// 設置滾動條的內邊距
self.webView.scrollView.scrollIndicatorInsets = self.webView.scrollView.contentInset;
} else {
self.automaticallyAdjustsScrollViewInsets = false;
}
2、根據 iOS11 UIScrollView 新增的兩個屬性:adjustContentInset 和 contentInsetAdjustmentBehavior
if (@available(iOS 11.0, *)) {
self.additionalSafeAreaInsets = UIEdgeInsetsMake(-STATUS_BAR_HEIGHT, 0, 0, 0);
// 如果使用了 navigationBar,又把它隱藏的情況, additionalSafeAreaInsets 要找到使它偏移的 Controller
// self.navigationController.additionalSafeAreaInsets = UIEdgeInsetsMake(--NAVI_BAR_HEIGHT, 0, 0, 0);
} else {
self.automaticallyAdjustsScrollViewInsets = false;
}
關于scrollView在iOS11新增的兩個屬性 adjustContentInset 和 contentInsetAdjustmentBehavior:
adjustContentInset 表示 contentView.frame.origin 偏移了 scrollview.frame.origin 多少;
是系統計算得來的,計算方式由 contentInsetAdjustmentBehavior 決定。
有以下幾種計算方式:
- UIScrollViewContentInsetAdjustmentAutomatic: 如果 scrollview 在一個automaticallyAdjustsScrollViewInsets = YES的controller上,并且這個 Controller 包含在一個 navigation controller 中,這種情況下會設置在 top & bottom 上 adjustedContentInset = safeAreaInset + contentInset 不管是否滾動。其他情況下與UIScrollViewContentInsetAdjustmentScrollableAxes 相同;
- UIScrollViewContentInsetAdjustmentScrollableAxes: 在可滾動方向上adjustedContentInset = safeAreaInset + contentInset,在不可滾動方向上adjustedContentInset = contentInset;
依賴于 scrollEnabled 和alwaysBounceHorizontal / vertical = YES,scrollEnabled 默認為 YES ,所以大多數情況下,計算方式還是 adjustedContentInset = safeAreaInset + contentInset - UIScrollViewContentInsetAdjustmentNever: adjustedContentInset = contentInset
- UIScrollViewContentInsetAdjustmentAlways: adjustedContentInset = safeAreaInset + contentInset
當 contentInsetAdjustmentBehavior 設置為UIScrollViewContentInsetAdjustmentNever 的時候,adjustContentInset 值不受 SafeAreaInset 值的影響。