WWDC 2016 Session 222 - 233 App 适配

这两个 Session 主要介绍了在 Xcode 8 与 iOS 10 中,进行 App 适配更方便的地方。
现在由于设备越来越多,屏幕的尺寸也在不断增加。从现在还支持的最古老的设备 4S 开始,到屏幕尺寸最大的 iPad Pro,再加上屏幕方向的支持和 iPad 中的 splitView,各种组合大概有 300 多种,要手动管理的话十分麻烦。
不过 Apple 帮你简化了大部分工作,现在需要关心的主要是 Traits。下面这张图简要介绍了 Traits 的几个例子:

Trait

下面首先介绍 Size Classes。Size Classes 在 iOS 8 中引入,它主要用于简化以下几个方面的操作:屏幕尺寸、屏幕方向、适配性(iPad splitView)。有了 Size Classes,你需要关心的只是可用空间的大小,你可以对屏幕内容有更精确的控制。

屏幕适配

Size Classes 主要分为两类:horizontalSizeClass 与 verticalSizeClass。每种又可细分为两类:Compact 与 Regular。

Size Classes

有了 Size Classes,只需要考虑上面图片中四种组合。不过一般来说主要考虑对宽度改变做出相应调整。Size Class 可以根据屏幕的情况动态调整(旋转等),并且还能方便的根据设备的情况对 View Controller 进行调整。


iPad 中的 splitView 在 iPhone 上则变为 navigation 的形式

iPad 中的 popOver 和 iPhone 中的 modal

下面介绍了一个重要的方法,针对 Trait 改变时进行调整,主要应用在 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()
        }
} } 

在每个 UITraitEnvironmet 中都会调用 traitCollectionDidChange(:) 方法,你只重写需要进行更改的部分。而在 Interface Builder、Asset catalog、UIAppearance 中,系统会帮你自动处理这个方法。

总结一下:

  • Trait 用于描述整个环境的变化,包括 Layout、外观、兼容性等。
  • 如果需要根据 Trait 的变化进行调整,重写traitCollectionDidChange(:) 方法。
  • Size Classes 简化了你需要考虑的事。
  • 系统会帮你处理大部分的工作。

下面有个 Demo 展示,主要是关于 Xcode 8 中如何方便的根据设备情况对 UI 进行定制。具体可以去官网看看 Session 222 的后半部分。

Session 233 主要做了几件事:

  1. 介绍了 Size 和 Size class 的基础
  2. 如何最有效地使用 UIKit
  3. 在前面介绍的基础上提升体验

Size 和 Size class 的基础

现有屏幕的各种尺寸及分辨率
如何分为四种 Size Class

之后介绍了一些因为不同的 Size 产生的差别,如 view 与 controller、presentation(在 modal 上的不同)、split view,session 222 也已经提过。

如何最有效地使用 UIKit

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

这里着重介绍了几个功能:

Asset Catalogs

Alignment Inset:可以定义一个 Inset,将图片最重要的部分展现出来。

Slicing:类似 Android 的点九,现在可以在 Asset Catalogs 里面配置需要切分的图片,将可拉伸与不可拉伸部分分隔开
,保证边缘的如圆角部分不会因图片拉伸产生变形。

Dynamic Type

可以根据 Trait Collection 的变化调整字体。

Layout Guides

根据 Margin 来进行 Layout:

自动根据合适的阅读宽度调整内容的范围以及字体的大小:

UIAppearance

下面这段代码介绍了一种方法,用于根据 Size class 来调整 UINavigationBar 的 BackgroundImage:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions:
[NSObject: AnyObject]?) -> Bool {
    //获取垂直方向为 compact 时的 trait
    let verticalCompactTrait = UITraitCollection(verticalSizeClass: .compact)
    //通过该 trait 获取 UINavigationBar compact 时的外观
    let compactAppearance = UINavigationBar.forTraitCollection(verticalCompactTrait)
    //设置背景图片
    compactAppearance.setBackgroundImage(nil, for: .default)
    
    let verticalRegularTrait = UITraitCollection(verticalSizeClass: .regular)
    let verticalAppearance = UINavigationBar.forTraitCollection(verticalRegularTrait)
    verticalAppearance.setBackgroundImage(UIImage(), for: .default)

} 

可以达到如下的效果:


虽然前面有提到 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.

简单来说,trait collection 可以表示某种环境下的 UI,比如 size class,屏幕的 scale 等等。使用 trait collection,就可以针对特定环境下的 UI 进行更改,而不影响其他环境的 UI。

于是你就可以根据这些 trait collection,根据不同的 trait 组合来调整 UI。这也是下面官方要讲的:

  1. 为不同设备、屏幕方向、尺寸进行设计
    • 不要这么做:只判断屏幕尺寸是否完全相等
    • 最好这样:设定一些条件来判断:制定规则
      • 使用 Size class
      • 将值与阈值相比
      • 将值与其它值进行比较
  2. 实现这些设计
    • 找出 app 的尺寸数据
    • 使用规则来决定应该如何设计
    • 将设计应用到 UI 中去
    • 关于代码适合放置的位置:
      • 这部分代码不适合放在 viewDidLoad() 中,因为这时候 superview 还没有确定,layout 也还没有起作用。只有在整个设计中不变的东西才放在 init() loadView() viewDidLoad() 中。
      • 这部分代码适合放在 viewWillLayoutSubviews() 中,这时候 view 已经在 superview 中,并且 layout 已经开始了。在这个方法里面适合调整一些 view controller 相关的东西。
      • 但要小心使用:
        • 尽量少放代码在这个方法中
        • 找出那些上次改变了的东西
        • 小心不要引发 layout 循环
  3. 复用组件
    • 设计一些在不同设计中通用的部件
    • 每一个部件都是一个 view controller
      • view 的层级与约束
      • 与其它 view controller 的联系
      • 与 app 中其它部分的联系

关于 layout,官方有个小 demo,演示如何实现以下效果:

即在屏幕旋转时,UIStackView 内部元素的方向也跟着旋转。
其实代码没几行:

class SimpleExampleViewController: UIViewController {

    @IBOutlet var stackView : UIStackView!
    override func viewWillLayoutSubviews() {
        let size = view.bounds.size
        let useWideDesign = size.width >= size.height
        //根据屏幕的宽高比较,决定是否要修改 stactView 内容方向
        if useWideDesign {
            stackView.axis = .horizontal
        } else {
            stackView.axis = .vertical
        }
    }
}

关于部件的复用这一块,这个 session 中还有一个比较长的 demo,地址在这里 ,需要 Xcode 8 与 iOS 10。

总而言之,这部分提出了一种类似于 web 中响应式设计的解决方案,在 web 中已经应用了挺久了,但是在原生的 app 中还比较新,并且也有一些拓展,根据屏幕的 trait 能进行更多的定制,包括点击操作的效果等等。虽然感觉在原生 app 中做这件事比较怪异,不过也期待有更多有趣的设计~

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,736评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,167评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,442评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,902评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,302评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,573评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,847评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,562评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,260评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,531评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,021评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,367评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,016评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,068评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,827评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,610评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,514评论 2 269

推荐阅读更多精彩内容