ViewController Programming Guide 笔记(九)

Building an Adaptive Interface

一个自适应的界面应该能响应 trait 和 size 的变化。在 view controller 层级上,你使用 traits 来粗略决定将要显示的内容以及对应 layout 布局。例如,当 size classes 发生变化时,你可以选择改变 view 的属性,显示或隐藏 views,或者显示完全不同的 views。在做出这些决定后,你使用 size 变化来调整内容。

Adapting to Trait Changes

Traits 给你一种根据不同环境配置 app 的途径,你可以使用他来粗略地调整你的界面元素。大部分改变,你可以直接通过 storyboard 文件来改变,但是一部分也需要代码来实现

Configuring Your Storyboard to Handle Different Size Classes

IB 可以很容易地使你的界面适配不同的 size classes,你可以使用 storyboard 编辑器在不同的 size class 下移除或增加指定的 view、layout 约束等元素,而不需要手动写代码去做这些事情。

下图展示了你可以使用 IB 工具做的操作

Image assets 是存储 app image 资源的好地方,每个 image asset 都包含了同一张图片的多个版本,以适应不同的设置。除了为视网膜屏提供不同尺寸外,你还可以为不同的 size classes 提供不同的 images。当配置好 image asset 之后, UIImageView 对象会自动根据当前 size classes 来选择图片

下图显示了不同 size classes 下的 image assets

Changing the Traits of a Child View Controller

Child VC 默认继承自 父 VCtraits,对于 traits 类似于 size class,不可能所有的 childVC 都与 父 VC 具有一样的 traits。例如,一个在 regular 环境下的 VC,可能会为自己 childVC 分配一个 compact size class。当你实现这样的 container VC 时,你可以通过在 container VC 上调用 setOverrideTraitCollection:forChildViewController: 方法来修改 child 的 traits

下面演示了你如何创建一组新的 traits 和相关的 childVC,你会在 父 VC 上执行这些 code,且仅需要执行一次,覆盖这些 traits 会使 childVC 在下一次 父 VC 发生变化时,childVC 仍然能够保持,直到你手动改变 traits 或从整个继承结构中移除 childVC

UITraitCollection* horizTrait = [UITraitCollection  
                 traitCollectionWithHorizontalSizeClass:UIUserInterfaceSizeClassRegular];
UITraitCollection* vertTrait = [UITraitCollection  
                 traitCollectionWithVerticalSizeClass:UIUserInterfaceSizeClassCompact];
UITraitCollection* childTraits = [UITraitCollection  
                 traitCollectionWithTraitsFromCollections:@[horizTrait, vertTrait]];

[self setOverrideTraitCollection:childTraits forChildViewController:self.childViewControllers[0]];

父 VCtraits 发生变化时,子 VC 仅仅继承那些没有被 父 VC 重写的 traits。比如上面父类的 horizontal size class 由 regular 变成 compact,childVC 却仍然保持 regular。 但如果是 displayScale 发生变化,childVC 的也会继承新的 displayScale

Adapting Presented View Controllers to a New Style

PresentedVC 在 horizontally regular 和 compact 环境下会自动适应,一般从 horizontally regular 到 horizontally compact,UIKit 会默认改变 presentation styles 为 UIModalPresentationFullScreen。对于自定义的 presentation styles ,你的 presentation controller 会决定这些自定义的行为然后调整相应的 presentation。

在某些情形下,例如触摸 bounds 边缘会 pop/dismiss 掉 popover,但是在 compact 环境下 popover 却会铺满整个屏幕。当默认的 adaptation style 不合适时,你可以让 UIKit 使用不同类型或完全不同的 VC 来适应全屏 style。

为了改变 presentation style 默认的自适应行为,分配一个 delegate 给相关 presentation controller。你可以通过 presentedVC 的 presentationController 属性来访问这个 presentation controller 。这个 presentation controller 在做出任何自适应相关的变化时会向你的 delegate 来商讨相关自适应事宜,你的 delegate 能够返回一个 presentation style,他会提供 presentation controller 展示一个不同的 VC

使用 delegate 的 adaptivePresentationStyleForPresentationController: 方法来指定一个不同的 presentation style,当转换成 compact 环境时,唯一支持的 styles 是两种全屏 styles 或 UIModalPresentationNone。返回 UIModalPresentationNone 告诉 presentation controller 忽略 compact 环境且继续使用之前的 presentation style。在这种情形下,popover 会忽略 size class 的变化,给你在所有设备上都有类似 iPad 上一样的效果,下图展示了这两种区别:

要完全替换 VC,需要实现 delegate 的 presentationController:viewControllerForAdaptivePresentationStyle: 方法,在 compact 环境下,你可能会使用这个方法来插入一个 navigation controller 到你的层级结构中,或载入一个专门为狭小空间设计的 VC。

Tips for Implementing Adaptive Popovers

当从 horizontally regular 到 horizontally compact,Popover 需要额外修改,对于 horizontally compact 默认的行为是全屏展示,因为 popovers 通常按下 bounds 边缘的 popover 按钮才能被 dismiss,而变成全屏展示通常会遮盖掉这个 dismiss 按钮,你可以通过如下方式进行补救:

  • 将 popover’s view controller push 到一个存在的 navigation stack 中
  • 在全屏时,增加 dismiss the popover 的控制操作,更好的选择是使用 presentationController:viewControllerForAdaptivePresentationStyle: 来置换出 popover,使用 navigation controller 给你一个 modal interface 并且放置一个 Done 按钮之类的来 dismiss
  • 使用 presentation controller delegate 来消除任何 adaptivity 改变,得到 popover presentation controller 然后分配一个 delegate 给他,并实现 adaptivePresentationStyleForPresentationController: 方法,从该方法中返回 UIModalPresentationNone 将导致 popover 继续以 iPad 上的方式显示

Responding to Size Changes

size 变化通常会在下面这些情况发生:

  • window 的尺寸发生变化,通常因为方向变化
  • 父 VC 会改变 childVC 的尺寸大小
  • presentation controller 会改变 presentedVC 的尺寸

当尺寸改变发生时,UIKit 会自动更新屏幕上可见 VC 的 size 和 position,如果你使用 Auto Layout 约束指定了 size 和 position,你的 app 会自动适应任意 size 改变并且能够运行在任意尺寸屏幕的设备上。

如果 Auto Layout 约束不足以达到你想要的,你可以使用 viewWillTransitionToSize:withTransitionCoordinator: 方法来对 layout 做成更改,你可以使用这个方法来创建 size 变化的动画,例如在整个界面旋转时,你可能会使用 transition coordinator 的 targetTransform 属性为你的界面创建一个 反旋转矩阵(counter-rotation matrix)


-EOF-

如果感觉此文对你有帮助,请随意打赏支持作者 😘

chengway

认清生活真相之后依然热爱它!

Subscribe to Talk is cheap, Show me the world!

Get the latest posts delivered right to your inbox.

or subscribe via RSS with Feedly!