WWDC 2016 Session 222 - 233 App 適配

這兩個(gè) Session 主要介紹了在 Xcode 8 與 iOS 10 中测僵,進(jìn)行 App 適配更方便的地方樊破。
現(xiàn)在由于設(shè)備越來越多巡语,屏幕的尺寸也在不斷增加缅疟。從現(xiàn)在還支持的最古老的設(shè)備 4S 開始分别,到屏幕尺寸最大的 iPad Pro,再加上屏幕方向的支持和 iPad 中的 splitView存淫,各種組合大概有 300 多種耘斩,要手動(dòng)管理的話十分麻煩。
不過 Apple 幫你簡(jiǎn)化了大部分工作桅咆,現(xiàn)在需要關(guān)心的主要是 Traits括授。下面這張圖簡(jiǎn)要介紹了 Traits 的幾個(gè)例子:

Trait

下面首先介紹 Size Classes。Size Classes 在 iOS 8 中引入岩饼,它主要用于簡(jiǎn)化以下幾個(gè)方面的操作:屏幕尺寸荚虚、屏幕方向、適配性(iPad splitView)籍茧。有了 Size Classes曲管,你需要關(guān)心的只是可用空間的大小,你可以對(duì)屏幕內(nèi)容有更精確的控制硕糊。

屏幕適配

Size Classes 主要分為兩類:horizontalSizeClass 與 verticalSizeClass。每種又可細(xì)分為兩類:Compact 與 Regular腊徙。

Size Classes

有了 Size Classes简十,只需要考慮上面圖片中四種組合。不過一般來說主要考慮對(duì)寬度改變做出相應(yīng)調(diào)整撬腾。Size Class 可以根據(jù)屏幕的情況動(dòng)態(tài)調(diào)整(旋轉(zhuǎn)等)螟蝙,并且還能方便的根據(jù)設(shè)備的情況對(duì) View Controller 進(jìn)行調(diào)整。


iPad 中的 splitView 在 iPhone 上則變?yōu)?navigation 的形式

iPad 中的 popOver 和 iPhone 中的 modal

下面介紹了一個(gè)重要的方法民傻,針對(duì) Trait 改變時(shí)進(jìn)行調(diào)整胰默,主要應(yīng)用在 View Controller 與 View 中。

override func traitCollectionDidChange(_ previousTraits: UITraitCollection?) {
    super.traitCollectionDidChange(previousTraits)
    if previousTraits?.horizontalSizeClass != traitCollection.horizontalSizeClass {
        switch traitCollection.horizontalSizeClass {
        case .compact:
            setupConstraintsForCompactEnvironment()
        case .unspecified: fallthrough
        case .regular:
            setupConstraintsForRegularEnvironment()
        }
} } 

在每個(gè) UITraitEnvironmet 中都會(huì)調(diào)用 traitCollectionDidChange(:) 方法漓踢,你只重寫需要進(jìn)行更改的部分牵署。而在 Interface Builder、Asset catalog喧半、UIAppearance 中奴迅,系統(tǒng)會(huì)幫你自動(dòng)處理這個(gè)方法。

總結(jié)一下:

  • Trait 用于描述整個(gè)環(huán)境的變化挺据,包括 Layout取具、外觀脖隶、兼容性等。
  • 如果需要根據(jù) Trait 的變化進(jìn)行調(diào)整暇检,重寫traitCollectionDidChange(:) 方法产阱。
  • Size Classes 簡(jiǎn)化了你需要考慮的事。
  • 系統(tǒng)會(huì)幫你處理大部分的工作块仆。

下面有個(gè) Demo 展示构蹬,主要是關(guān)于 Xcode 8 中如何方便的根據(jù)設(shè)備情況對(duì) UI 進(jìn)行定制。具體可以去官網(wǎng)看看 Session 222 的后半部分榨乎。

Session 233 主要做了幾件事:

  1. 介紹了 Size 和 Size class 的基礎(chǔ)
  2. 如何最有效地使用 UIKit
  3. 在前面介紹的基礎(chǔ)上提升體驗(yàn)

Size 和 Size class 的基礎(chǔ)

現(xiàn)有屏幕的各種尺寸及分辨率
如何分為四種 Size Class

之后介紹了一些因?yàn)椴煌?Size 產(chǎn)生的差別怎燥,如 view 與 controller、presentation(在 modal 上的不同)蜜暑、split view铐姚,session 222 也已經(jīng)提過。

如何最有效地使用 UIKit

  1. Xcode 的工具:
    • Interface Builder
    • Asset Catalogs
  2. UIKit
    • Auto Layout
    • UITraitCollection
    • Dynamic Type
    • Layout Guides
    • UIAppearance

這里著重介紹了幾個(gè)功能:

Asset Catalogs

Alignment Inset:可以定義一個(gè) Inset肛捍,將圖片最重要的部分展現(xiàn)出來隐绵。

Slicing:類似 Android 的點(diǎn)九,現(xiàn)在可以在 Asset Catalogs 里面配置需要切分的圖片拙毫,將可拉伸與不可拉伸部分分隔開
依许,保證邊緣的如圓角部分不會(huì)因圖片拉伸產(chǎn)生變形。

Dynamic Type

可以根據(jù) Trait Collection 的變化調(diào)整字體缀蹄。

Layout Guides

根據(jù) Margin 來進(jìn)行 Layout:

自動(dòng)根據(jù)合適的閱讀寬度調(diào)整內(nèi)容的范圍以及字體的大星吞:

UIAppearance

下面這段代碼介紹了一種方法,用于根據(jù) Size class 來調(diào)整 UINavigationBar 的 BackgroundImage:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions:
[NSObject: AnyObject]?) -> Bool {
    //獲取垂直方向?yàn)?compact 時(shí)的 trait
    let verticalCompactTrait = UITraitCollection(verticalSizeClass: .compact)
    //通過該 trait 獲取 UINavigationBar compact 時(shí)的外觀
    let compactAppearance = UINavigationBar.forTraitCollection(verticalCompactTrait)
    //設(shè)置背景圖片
    compactAppearance.setBackgroundImage(nil, for: .default)
    
    let verticalRegularTrait = UITraitCollection(verticalSizeClass: .regular)
    let verticalAppearance = UINavigationBar.forTraitCollection(verticalRegularTrait)
    verticalAppearance.setBackgroundImage(UIImage(), for: .default)

} 

可以達(dá)到如下的效果:


雖然前面有提到 trait缺前,但是還有一些不太理解蛀醉,查了一下官方文檔:

A trait collection describes the iOS interface environment for your app, including traits such as horizontal and vertical size class, display scale, and user interface idiom. To create an adaptive interface, write code to adjust your app’s layout according to changes in these traits.

簡(jiǎn)單來說,trait collection 可以表示某種環(huán)境下的 UI衅码,比如 size class拯刁,屏幕的 scale 等等。使用 trait collection逝段,就可以針對(duì)特定環(huán)境下的 UI 進(jìn)行更改垛玻,而不影響其他環(huán)境的 UI。

于是你就可以根據(jù)這些 trait collection奶躯,根據(jù)不同的 trait 組合來調(diào)整 UI帚桩。這也是下面官方要講的:

  1. 為不同設(shè)備、屏幕方向巫糙、尺寸進(jìn)行設(shè)計(jì)
    • 不要這么做:只判斷屏幕尺寸是否完全相等
    • 最好這樣:設(shè)定一些條件來判斷:制定規(guī)則
      • 使用 Size class
      • 將值與閾值相比
      • 將值與其它值進(jìn)行比較
  2. 實(shí)現(xiàn)這些設(shè)計(jì)
    • 找出 app 的尺寸數(shù)據(jù)
    • 使用規(guī)則來決定應(yīng)該如何設(shè)計(jì)
    • 將設(shè)計(jì)應(yīng)用到 UI 中去
    • 關(guān)于代碼適合放置的位置:
      • 這部分代碼不適合放在 viewDidLoad() 中朗儒,因?yàn)檫@時(shí)候 superview 還沒有確定,layout 也還沒有起作用。只有在整個(gè)設(shè)計(jì)中不變的東西才放在 init() loadView() viewDidLoad() 中醉锄。
      • 這部分代碼適合放在 viewWillLayoutSubviews() 中乏悄,這時(shí)候 view 已經(jīng)在 superview 中,并且 layout 已經(jīng)開始了恳不。在這個(gè)方法里面適合調(diào)整一些 view controller 相關(guān)的東西檩小。
      • 但要小心使用:
        • 盡量少放代碼在這個(gè)方法中
        • 找出那些上次改變了的東西
        • 小心不要引發(fā) layout 循環(huán)
  3. 復(fù)用組件
    • 設(shè)計(jì)一些在不同設(shè)計(jì)中通用的部件
    • 每一個(gè)部件都是一個(gè) view controller
      • view 的層級(jí)與約束
      • 與其它 view controller 的聯(lián)系
      • 與 app 中其它部分的聯(lián)系

關(guān)于 layout,官方有個(gè)小 demo烟勋,演示如何實(shí)現(xiàn)以下效果:

即在屏幕旋轉(zhuǎn)時(shí)规求,UIStackView 內(nèi)部元素的方向也跟著旋轉(zhuǎn)。
其實(shí)代碼沒幾行:

class SimpleExampleViewController: UIViewController {

    @IBOutlet var stackView : UIStackView!
    override func viewWillLayoutSubviews() {
        let size = view.bounds.size
        let useWideDesign = size.width >= size.height
        //根據(jù)屏幕的寬高比較卵惦,決定是否要修改 stactView 內(nèi)容方向
        if useWideDesign {
            stackView.axis = .horizontal
        } else {
            stackView.axis = .vertical
        }
    }
}

關(guān)于部件的復(fù)用這一塊阻肿,這個(gè) session 中還有一個(gè)比較長(zhǎng)的 demo,地址在這里 沮尿,需要 Xcode 8 與 iOS 10丛塌。

總而言之,這部分提出了一種類似于 web 中響應(yīng)式設(shè)計(jì)的解決方案畜疾,在 web 中已經(jīng)應(yīng)用了挺久了赴邻,但是在原生的 app 中還比較新,并且也有一些拓展啡捶,根據(jù)屏幕的 trait 能進(jìn)行更多的定制姥敛,包括點(diǎn)擊操作的效果等等。雖然感覺在原生 app 中做這件事比較怪異瞎暑,不過也期待有更多有趣的設(shè)計(jì)~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末彤敛,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子了赌,更是在濱河造成了極大的恐慌臊泌,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,496評(píng)論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件揍拆,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡茶凳,警方通過查閱死者的電腦和手機(jī)嫂拴,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,187評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來贮喧,“玉大人筒狠,你說我怎么就攤上這事∠渎伲” “怎么了辩恼?”我有些...
    開封第一講書人閱讀 157,091評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我灶伊,道長(zhǎng)疆前,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,458評(píng)論 1 283
  • 正文 為了忘掉前任聘萨,我火速辦了婚禮竹椒,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘米辐。我一直安慰自己胸完,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,542評(píng)論 6 385
  • 文/花漫 我一把揭開白布翘贮。 她就那樣靜靜地躺著赊窥,像睡著了一般。 火紅的嫁衣襯著肌膚如雪狸页。 梳的紋絲不亂的頭發(fā)上锨能,一...
    開封第一講書人閱讀 49,802評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音肴捉,去河邊找鬼腹侣。 笑死,一個(gè)胖子當(dāng)著我的面吹牛齿穗,可吹牛的內(nèi)容都是我干的傲隶。 我是一名探鬼主播,決...
    沈念sama閱讀 38,945評(píng)論 3 407
  • 文/蒼蘭香墨 我猛地睜開眼窃页,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼跺株!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起脖卖,我...
    開封第一講書人閱讀 37,709評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤乒省,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后畦木,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體袖扛,經(jīng)...
    沈念sama閱讀 44,158評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,502評(píng)論 2 327
  • 正文 我和宋清朗相戀三年十籍,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了蛆封。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,637評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡勾栗,死狀恐怖惨篱,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情围俘,我是刑警寧澤砸讳,帶...
    沈念sama閱讀 34,300評(píng)論 4 329
  • 正文 年R本政府宣布琢融,位于F島的核電站,受9級(jí)特大地震影響簿寂,放射性物質(zhì)發(fā)生泄漏漾抬。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,911評(píng)論 3 313
  • 文/蒙蒙 一陶耍、第九天 我趴在偏房一處隱蔽的房頂上張望奋蔚。 院中可真熱鬧,春花似錦烈钞、人聲如沸泊碑。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,744評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽馒过。三九已至,卻和暖如春酗钞,著一層夾襖步出監(jiān)牢的瞬間腹忽,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,982評(píng)論 1 266
  • 我被黑心中介騙來泰國(guó)打工砚作, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留窘奏,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,344評(píng)論 2 360
  • 正文 我出身青樓葫录,卻偏偏與公主長(zhǎng)得像着裹,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子米同,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,500評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容