在iPhoneX上適配你的App

在iPhone X上構建你的APP

原文鏈接,文章為 Building Apps for iPhone X Fall 2017 - Session 201 - iOS 的文字實錄。以視頻中主人公為第一視角,結合本文作者的一些理解的進行了內容講解。

iPhone X

前言

要適配你的App,只需按照 iOS11 SDK 進行修改,就可以充分利用iPhone X搭載的超視網膜顯示屏。


如果你的App主要基于標準的 UIKit 控件,并且使用 AutoLayout 那么接下來的任務就會很輕松了,因為絕大多數工作都由 UIKit 為你代勞了。


如果你使用的是自定義控件沒有使用 AutoLayout ,再或者你的 App 是一款自定義全屏的 App 像很多游戲那樣,你也不必擔心,雖然你確實有些工作要做。但整個適配過程中并沒有什么難點,而且我們有很多內建支持工具,比如全新推出的 Safe Area Layout Guide


無論如何,你都需要全面測試你的 App,尤其是在橫屏模式下,以確保萬無一失。

iPhone X Simulator

最新版 Xcode 包含支持 iPhone X 的 模擬器 讓你可以改變絕大多數的布局, 尤其是調整關于 Safe Area 的布局。對于一些 App, 比如使用了 Metal 或是使用了前置攝像頭等硬件功能的 App ,最好在實際設備上進行測試。


讓我們來看看全新的 iPhone X Simulator:

iPhoneX

同其他 iPhone 或 iPad Simulator 一樣,你可以直接使用系統內置 App,這樣就可以很好的通過實例觀察不同的 UIKit 組件在 iPhone X 上的表現。


比如文件App,就展示了很多最新的 iOS11 API 的實際應用。比如一體式的 SerchBar 和 Large NavigationBar Titles 。


別忘了,你還可以在 Simulator 中登錄 iCloud 帳戶,并訪問你的 iCloud Drive 。這樣你就可以方便的將文件或者照片等測試文件傳輸到 Simulator 中。

iCloud

另外一個不錯的例子就是通訊錄,它展示了 TableView 如何在 iPhone X 上呈現。一定要將 Simulator 旋轉至橫向模式。這樣就可以看到一些效果,比如 Section Header 橫跨屏幕,而 TableViewCell 則遵照 SafeArea 的原則,并保持縮進。稍后還會講到 TableView 。

Address

接下來我們來看看我負責的項目 WWDC App,我花了一點時間,讓它適配 iPhone X,我想分享一下我遇到的有關布局的問題以及我的解決方案。

適配 iPhone X

WWDC是一款真實存在的App,它已經面世了很多年。這些年來,很多工程師都參與了它的編寫。它既有很多標準控件和 AutoLayout,也包含自定義View。App 中較老的部分甚至使用了手動布局。我會用這款 App 來強調三處需要針對 iPhone X 進行適配的地方。


首先,我在 Xcode 9 中打開工程文件,將 Base SDK 設為 iOS11,這樣就可以以原生分辨率運行 App 了。


當設置你的 App 時,如果你發現 App 沒有完整在 iPhone X 下運行,請檢查一下你是否配置了 Launch Storyboard,因為這部分設置是必須的。(編輯注: 如果沒有使用Launch Storyboard的話)


我們的初始視圖是 Videos 標簽頁,效果如下圖看起來還不錯。這些全部使用的是今年的新代碼,其中使用了遵循 AutoLayout 的 UICollectionView,以及 UINavigationBar 和 UIToolBar 控件等。所以絕大多數界面的布局都沒問題,因為 UIKit 為我代勞了大部分工作。

有一個地方沒有使用 AutoLayout ,那就是 News 標簽頁。效果如下圖,其實這個 View 看起來還不錯,盡管所有 UI 都是手動布局,盡管我們沒有直接使用 AutoLayout,負責布局的代碼也會注意到 layout margin insets,UIKit 會自動調整布局適應 Safe Area。

AutoLayout 適配 Safe Area

我遇到的第一個適配問題就是再 News 標簽頁中的全屏圖片瀏覽器。盡管這個 View 使用了 AutoLayout ,但其中 PageControl 的位置太靠下了,已經與主屏幕指示器重疊在了一起。


這里的主要問題在于頁面空間的底部約束關聯的是 SuperView ,也就是 Home 指示器后面的整個屏幕。所以,我們不應該根據父視圖進行約束,而應該將 PageControl 按照底部的 Safe Area Layout Guide 進行約束。修改方式如下:

在調整約束前,需要先啟用 StoryBoard/Xib 的 Safe Area Layout Guide。Xcode 9 以前的 StoryBoard/Xib 不會自動啟用該選項。需要進入 文檔檢查器 -> Interface Builder Document -> 勾選 Use Safe Area Layout Guides 復選框

注意: iOS StoryBoard 打開 Use Safe Area Layout Guides 功能會自動升級綁定在 top 和 bottom 的 layout guide 約束,leading Edge 以及 trailing Edge。因此,勾選后一定要檢查測試所有 AutoLayout 的約束。

Storyboard Safe Area

將如圖所示右側的 Use Safe Area Layout Guide 勾選上。

勾選之后,效果如下:



多出一個叫 Safe Area 的區域,如上圖所示。

此時我們來看下 PageControl 的約束,之前約束都是與 SuperView 構建的關系,現在全部變成了 Safe Area。這樣就不會遮擋 Home 指示器了。 怎么樣很簡單吧?


Xib Safe Area

操作步驟與 Storyboard 相同

  1. 先勾選 Use Safe Area Layout Guide
  2. 再修改 PageControl 的 bottom 約束,將 SuperView 改成與 Safe Area

操作步驟如gif圖


經過上述調整,我們的 PageControl 就已經不再遮擋 Home 指示器了,并且在橫豎屏下均有效。


SearchBar 適配問題

接下來,來看看我遇到的第二個問題。問題出在 Videos 標簽頁,同樣看上去也還不錯,但當我調出 SearchBar 時,看起來位置似乎有問題,讓我們和通訊錄進行一下對比。


SearchBar 的背景顏色似乎不太對,Size 也不太對。如果我旋轉到橫屏模式,可以看出 SearchBar 和 Cancel 按鈕都被屏幕的圓角裁剪掉了一部分。


這個例子說明 Safe Area 的存在顯得至關重要,對于這種搜索欄 WWDC 的做法是直接顯示了一個 UISearchController ,而在 iOS 11 中 SearchBar 可以集成在 NavigationBar 中,并且給出正確的顯示方式。讓我們來看下代碼如何修改:


這是顯示 SearchController 的代碼,需要做兩處改動。

  1. 將 searchController 賦值給 navigationItem.searchController
  2. 讓 searchController 變為活躍狀態

注意: 該過程只在 iOS 11 下有效,因此,其他版本保持原有行為。

修改前:

    fileprivate func presentSearchController(initialSearchTeat searchTest: String? = nil) {
        let searchController = UISearchController(searchResultsController: nil)
        searchController.searchResultsUpdater = self as? UISearchResultsUpdating
        searchController.obscuresBackgroundDuringPresentation = false
        searchController.searchBar.text = searchTest
        
        present(searchController, animated: true, completion: nil)
    }

修改后:

    fileprivate func presentSearchController(initialSearchTeat searchTest: String? = nil) {
        let searchController = UISearchController(searchResultsController: nil)
        searchController.searchResultsUpdater = self as? UISearchResultsUpdating
        searchController.obscuresBackgroundDuringPresentation = false
        searchController.searchBar.text = searchTest
        
        if #available(iOS 11.0, *) {
            self.navigationItem.searchController = searchController
            searchController.isActive = true
        } else {
            present(searchController, animated: true, completion: nil)
        }
    }

現在 SearchBar 剛好在 Safe Area 中,并且這全部是 NavigationBar 自動幫我們處理的。如果你的 UI 效果中有 SearchBar 在 navigationBar 上的話,你一定要在 iOS 11 上做類似的處理。

TableView 適配問題

現在我們來看看 App 中的第三處改動,需要改進的地方。


如下是 Schedule 標簽頁,我們使用了 UITableView ,布局在豎屏模式下看起了不錯,但這里搜索欄的樣式也不太對。這個搜索欄恰好是作為 Header 視圖插入到 TableView 中的。但我們可以像剛才那樣改動,也就是讓 SearchBar 集成到 NavigationBar 中。

布局切換到橫屏模式所有UI看上去都遵循了 Safe Area 布局,但仔細觀察 TableView 的 SectionHeader ,它自定義的 BackgroundColor 似乎有問題,顏色應該像通訊錄 App 里的 TableView 那樣一直延伸到屏幕邊緣。

運行下代碼會發現,App 將背景顏色設置給了 headerView 的 contentView ,這看上去很合理。

    func tableView(_ tableView: UITableView, willDisplayHeaderView view: UIView, forSection section: Int) {
        let header = view as! UITableViewHeaderFooterView
        let font = UIFont.preferredFont(forTextStyle: .headline)
        
        header.textLabel?.font = font
        
        header.contentView?.backgroundColor = UIColor.lightGray
    }

事實上,在除了 iPhone X 之外的 iPhone 上都沒有這個問題。那問題出在了哪里呢?

我們要研究下 TableView 在 iPhone X 上是如何布局 Cell 的。

原理

為了幫助大家理解,我們通過 Xcode 的 View Hierarchy Debugger 進行視圖層級的查看。


這是我們剛剛看到的視圖,通過 View Hierarchy Debugger 可以調節視圖的層級和控制視圖的顯示/隱藏。

只顯示 TableView ,你會發現它的尺寸是整個屏幕。

調節可見范圍來顯示 TableView 的 Cell 。

你會發現 Cell 是與屏幕一樣寬的。

選中其中一個 Cell。

再用 Safe Area 來表示它的位置。

繼續調節可見范圍,我們可以看到 Cell 的 contentView ,自動布局在了 Safe Area 中。

雖然 Cell 的 Size 與屏幕一樣,但 Cell 的 contentView 卻和 Safe Area 的 Size 相同。
這樣發生了剛剛我們發現的問題。

剛剛我們看到的界面有些混亂,我們進行一些簡化并加上一些標記。

默認情況下,TableViewCell 會包含 ContentView,這樣就可以將內容適配在 Safe Area 內部。但這種行為是可以由你控制的。

在 Xcode 中你可以勾選 ContentView 的 Insets To Safe Area 選項,代碼中也有對應的屬性可以設置。如果不勾選或不設置,contentView 就不會適配 Safe Area,而是會與 cell 一樣大小。

無論 ContentView 如何設置,它的 Layout Margin 始終默認與 Safe Area 關聯。與 ContentView 適配類似,也有一些屬性可以讓你控制 Layout Margin 。關于這一點以及其他與邊距相關的選項你可以查閱文檔以及 WWDC 視頻。

解決方案

已經知道了原因是 Cell 的 contentView 的 Size 是與 Safe Area 相同的。通過代碼我們可以了解到,我們只設置了 contentView 的背景顏色。此時,我們有幾種解決方案來解決這個問題。
其中一種是禁用 TableView 的默認將 ContentView 適配 Safe Area 的行為,但這樣會影響 contentView 里的其他內容。
這里最好的解決方案就是設定 backgroundView 的 backgroundColor。backgroundView 與 contentView 不同,它與 Cell 是一樣大小,不受 Safe Area 影響。

    func tableView(_ tableView: UITableView, willDisplayHeaderView view: UIView, forSection section: Int) {
        let header = view as! UITableViewHeaderFooterView
        let font = UIFont.preferredFont(forTextStyle: .headline)
        
        header.textLabel?.font = font
        
        header.backgroundView?.backgroundColor = UIColor.lightGray
    }

修改完畢后,編譯運行。顏色就充滿了整個 Cell 。但 ContentView 中的內容并沒有發生變化。


以上就是我在為 WWDC 適配 iPhone X 的時候遇到的三個問題示例。

總結

適配 iPhone X ,需要注意以下幾點:

  • 遵循 iOS 11 SDK,使用 Launch Storyboard,可以讓你的 App 與原生分辨率一致
  • 測試UI時,橫豎屏幕都要進行,絕大多數問題出在橫屏下(左右橫屏都要測)
  • 遵循 Safe Area 可以避免絕大多數適配問題
    • AutoLayout: 設置 safeAreaLayoutGuide
    • 手動布局: 使用 safeAreaInsets ,自由計算所需布局的數據
  • 不要讓控件遮擋屏幕底部的 Home 指示器

關于 Home 指示器以及 iPhone X 設計方面的內容,請查看

Session Name Session Number From
Designing for iPhone X Session 801 Fall 2017
AutoLayout Techniques in Interface Builder Session 412 WWDC 2017
Modern User Interaction on iOS Session 219 WWDC 2017
Updating Your App for iOS 11 Session 204 WWDC 2017

一定要看 Designing for iPhone X 這個 Session,因為有很多關于 iPhone X 適配的細節包含在其中。

版權聲明: QC-L, 如需轉載請聯系作者并標明出處,謝謝

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,182評論 6 543
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,489評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 178,290評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,776評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,510評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,866評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,860評論 3 447
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,036評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,585評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,331評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,536評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,058評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,754評論 3 349
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,154評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,469評論 1 295
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,505評論 2 379

推薦閱讀更多精彩內容