自適應(yīng)界面能最大的利用可用空間。自適應(yīng)意味著可以調(diào)整內(nèi)容很好的適配任何iOS設(shè)備。iOS中自適應(yīng)model支持簡單動態(tài)的方法來重新排列和調(diào)整內(nèi)容以應(yīng)對變化。當你利用該model棒仍,簡單app可以使用很少額外代碼,以適應(yīng)截然不同的屏幕尺寸(如圖12-1所示)蝎困。
建立自適應(yīng)界面的重要工具是Auto Layout。使用Auto Layout倍啥,定義規(guī)則(稱為約束)管理視圖控制器視圖的布局禾乘。可以在界面構(gòu)建器中創(chuàng)建可視化的規(guī)則或者以編程的方式虽缕。當父視圖的大小改變始藕,iOS根據(jù)指定的約束,自動調(diào)整視圖的大小和位置氮趋。
自適應(yīng)model的另一個重要組成部分是trait伍派。trait描述視圖控制器和視圖必須操作的環(huán)境。trait幫助你作出界面決定凭峡。
trait規(guī)則
當約束并不足以管理布局時,視圖控制器有機會做出改變决记。視圖控制器摧冀、視圖和一些其他對象管理trait集合,trait集合指定該對象當前環(huán)境系宫。表12-1描述了trait以及如何使用trait來影響用戶界面索昂。
Trait | 例子 | 描述 |
---|---|---|
horizontalSizeClass | UIUserInterfaceSizeClassCompact | 該trait指定界面的總體寬度。使用trait做低級別布局決定扩借,例如視圖是否垂直堆放椒惨,并排顯示,隱藏或以其他方式顯示潮罪。 |
verticalSizeClass | UIUserInterfaceSizeClassRegular | 該traint指定界面的總體高度康谆。如果設(shè)計要求所有內(nèi)容都在屏幕上,且沒有滾動嫉到,使用trait做布局決定沃暗。 |
displayScale | 2.0 |
該trait指定內(nèi)容是以Retina或標準分辨率方式顯示。使用它(如果需要)進行像素級別布局決定或選擇顯示哪種版本的圖片何恶。 |
userInterfaceIdiom | UIUserInterfaceIdiomPhone | 該trait提供向后的兼容性并指定app在哪種類型的設(shè)備上運行孽锥。盡可能避免使用該trait。對于布局,使用水平惜辑、垂直size類代替 |
表12-1 trait
使用trait來決定如何present用戶界面唬涧。當在界面構(gòu)建器中構(gòu)建你的界面時,使用trait改變顯示或用來適應(yīng)不同約束的視圖和圖像盛撑。許多UIKit類碎节,如 UIImageAsset,調(diào)整指定的trait提供的信息撵彻。
這里有一些提示幫助你理解何時使用不同類型的trait:
- 使用size類來更改界面钓株。當size類改變時,添加或刪除視圖陌僵、添加或刪除子視圖控制器或改變布局約束轴合。也可以什么都不做,使用現(xiàn)有布局約束讓界面自適應(yīng)碗短。
- 永遠不要假設(shè)視圖的size類為指定高度或?qū)挾仁芨稹R晥D控制器的size類會因為很多原因改變。例如偎谁,iPhone上的容器視圖控制器可以使其子視圖控制器以不同的方式顯示它的內(nèi)容总滩。
- 適當使用界面構(gòu)建器為每個size類指定不同的布局約束。使用界面構(gòu)建器指定約束比你自己添加或刪除約束簡單巡雨。視圖控制器通過storyboard中的約束闰渔,自動處理size類變化。關(guān)于為不同size類配置布局約束的更多信息铐望,參見配置storyboard處理不同size類(Configuring Your Storyboard to Handle Different Size Classes)冈涧。
- 避免使用idiom信息來決定界面布局或內(nèi)容。iPad和iPhone上運行的app通常顯示相同的信息正蛙,應(yīng)該使用size類進行布局督弓。
什么時候trait和size發(fā)生變化?
trait很少發(fā)生變化乒验,但他們確實會發(fā)生變化愚隧。UIKit基于底層環(huán)境,更新視圖控制器的trait锻全。size類trait比顯示比例trait更容易發(fā)生變化狂塘。idiomtrait很少發(fā)生改變。size類發(fā)生變化的原因如下:
視圖控制器窗口的垂直或水平size類發(fā)生變化鳄厌,通常是因為設(shè)備發(fā)生旋轉(zhuǎn)睹耐。
容器視圖控制器的垂直或水平size類發(fā)生變化。
容器視圖控制器修改當然視圖控制器的垂直或水平size類部翘。
視圖控制器層級中size類發(fā)生變化會傳遞到視圖控制器硝训。窗口對象作為層級結(jié)構(gòu)的根,為其根視圖控制器提供基準size類trait。當設(shè)備橫豎屏切換時窖梁,窗口更新自己的size類信息赘风,并將該信息傳遞給視圖層級結(jié)構(gòu)。容器視圖控制器可以將變更傳遞給未修改的子視圖控制器纵刘,或者可以覆蓋每個子視圖控制器的trait邀窃。
在iOS8及后續(xù)版本,窗口原點總是在左上角假哎,當設(shè)備橫豎屏切換時瞬捕,窗口的bound發(fā)生變化。窗口的size變更和其他與trait變化相關(guān)的變更傳遞到視圖控制器層級結(jié)構(gòu)舵抹。對于層級結(jié)構(gòu)中的視圖控制器肪虎,UIKit調(diào)用以下方法來記錄這些變化:
- willTransitionToTraitCollection:withTransitionCoordinator:方法告訴每個相關(guān)視圖控制器,trait即將改變惧蛹。
- viewWillTransitionToSize:withTransitionCoordinator:方法告訴每個相關(guān)視圖控制器扇救,size即將改變。
- traitCollectionDidChange:方法告訴每個相關(guān)視圖控制器香嗓,trait已經(jīng)發(fā)生改變迅腔。
當遍歷視圖控制器層級結(jié)構(gòu),UIKit記錄視圖控制器的變化靠娱。如果一個容器視圖控制器覆蓋其子視圖控制器的size類沧烈,當容器視圖控制器的size類發(fā)生變化時,不通知這些子視圖控制器像云。類似的锌雀,如果容器視圖控制器的視圖有一個固定的寬度和高度,它不接收size變更通知苫费。
圖12-2展示了當iPhone6旋轉(zhuǎn)時汤锨,視圖控制器的trait和視圖size如何更新双抽。從豎屏旋轉(zhuǎn)到橫屏使屏幕的垂直size類從regular變?yōu)閏ompact百框。size類的改變,相關(guān)視圖size類的改變傳遞到視圖層級結(jié)構(gòu)牍汹。在渲染視圖到新size后铐维,UIKit在調(diào)用視圖控制器的traitCollectionDidChange:
方法前適應(yīng)size類和視圖size變更。
不同設(shè)備的默認size類
每個iOS設(shè)備都有一組默認的size類慎菲,當設(shè)計界面時嫁蛇,可以作為參考。表12-2列出了設(shè)備在豎屏和橫屏時的size類露该。表中未列出的設(shè)備的size類與使用相同屏幕尺寸的設(shè)備相同睬棚。
設(shè)備 | 豎屏 | 橫屏 |
---|---|---|
iPad (all)iPad Mini | Vertical size class: RegularHorizontal size class: Regular | Vertical size class: RegularHorizontal size class: Regular |
iPhone 6 Plus | Vertical size class: RegularHorizontal size class: Compact | Vertical size class: CompactHorizontal size class: Regular |
iPhone 6 | Vertical size class: RegularHorizontal size class: Compact | Vertical size class: CompactHorizontal size class: Compact |
iPhone 5siPhone 5ciPhone 5 | Vertical size class: RegularHorizontal size class: Compact | Vertical size class: CompactHorizontal size class: Compact |
iPhone 4s | Vertical size class: RegularHorizontal size class: Compact | Vertical size class: CompactHorizontal size class: Compact |
表12-2 不同屏幕尺寸設(shè)備的size類
重要:永遠不要假設(shè)app會在特定size類的設(shè)備上顯示。當決定如何配置對象時,總是要檢查該對象trait約束中的size類抑党。