ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
[TOC=5] * * * * * >原文链接 :[The Adaptive Model](https://developer.apple.com/library/content/featuredarticles/ViewControllerPGforiPhoneOS/TheAdaptiveModel.html#//apple_ref/doc/uid/TP40007457-CH19-SW1) 自适应界面是充分利用可用空间的界面。 适应性意味着能够调整您的内容,使其适合任何 iOS 设备。iOS 中的自适应模型支持简单但动态的方式来重新排列和调整内容以响应更改。 当你利用这个模型时,只需要很少的额外代码,一个应用程序可以适应不同的屏幕尺寸(如图 12-1 所示)。 ###### 图 12-1 适应不同的设备和方向 ![](https://developer.apple.com/library/content/featuredarticles/ViewControllerPGforiPhoneOS/Art/VCPG_AdaptiveModel_13-1_2x.png) 自动布局是构建自适应界面的重要工具。使用自动布局,可以定义管理视图控制器视图布局的规则(称为约束)。可以在 Interface Builder 中以可视方式创建这些规则,也可以在代码中以编程方式创建。当父视图的大小发生变化时,iOS 会根据您指定的约束条件自动调整其大小并重新定位视图。 特征是适应性模型的另一个重要组成部分。特征描述了您的视图控制器和视图必须操作的环境。特征可以帮助你做出关于界面的高层决策。 ### 第一节 特征的作用 当仅依靠约束不足以管理布局时,视图控制器有几个机会进行更改。视图控制器、视图和其他一些对象管理一个指定与该对象关联的当前环境的特征集合。表 12-1 描述了这些特征以及如何使用它们来影响用户界面。 ###### 表12-1 特征 | 特征 | 例子 | 描述 | | --- | --- | --- | | [horizontalSizeClass](https://developer.apple.com/documentation/uikit/uitraitcollection/1623508-horizontalsizeclass) | [UIUserInterfaceSizeClassCompact](https://developer.apple.com/documentation/uikit/uiuserinterfacesizeclass/uiuserinterfacesizeclasscompact) | 这个特质表达了界面的一般宽度。 使用它来进行粗层次的布局决策,比如视图是垂直堆放的,是并排显示的,还是隐藏的,或者是用另一种方式显示。 | | [verticalSizeClass](https://developer.apple.com/documentation/uikit/uitraitcollection/1623513-verticalsizeclass) | [UIUserInterfaceSizeClassRegular](https://developer.apple.com/documentation/uikit/uiuserinterfacesizeclass/uiuserinterfacesizeclassregular) | 这个特质表达了界面的一般高度。 如果设计要求所有内容都在屏幕上不滚动且适配屏幕,那么使用这个特性来做布局决定。 | | [displayScale](https://developer.apple.com/documentation/uikit/uitraitcollection/1623519-displayscale) | 2.0 | 这个特性表明内容是显示在视网膜显示器还是标准分辨率显示器上。 使用它(根据需要)进行像素级布局决策或选择要显示的图像版本。 | | [userInterfaceIdiom](https://developer.apple.com/documentation/uikit/uitraitcollection/1623521-userinterfaceidiom) | [UIUserInterfaceIdiomPhone](https://developer.apple.com/documentation/uikit/uiuserinterfaceidiom/uiuserinterfaceidiomphone) | 这个特性提供了向后兼容性,并传达你的应用程序运行的设备类型。 尽可能避免使用这个特质。 对于布局决定,请使用 horizontalSizeClass 、verticalSizeClass ]。 | 使用特质来决定如何呈现用户界面。在 Interface Builder 中构建界面时,使用特征来更改显示的视图和图像,或使用特征来应用不同的约束集。许多 UIKit 类(如 `UIImageAsset` )使用您指定的特征来定制它们提供的信息。 这里有一些技巧可以帮助你理解什么时候使用不同类型的特质: * **使用 Size class 对界面进行粗略更改**。 Size class 更改是添加或删除视图,添加或删除子视图控制器或更改布局约束的适当时间。 也可以不做任何事情,让界面使用现有的布局约束自动适应。 * **不要假设一个 Size class 类对应于一个视图的特定宽度或高度**。视图控制器的 Size class 可以改变的原因很多。 例如,iPhone 上的容器视图控制器可能会使其一个子控制器强制横屏以不同方式显示内容。 * **使用 Interface Builder 为每个 Size class 指定不同的布局约束**。使用 Interface Builder 来指定约束要比自己添加和删除约束简单得多。视图控制器通过应用故事板中的相应约束条件来自动处理 Size class 更改。有关为不同 Size class 配置布局约束的信息,请参 [Configuring Your Storyboard to Handle Different Size Classes](https://developer.apple.com/library/content/featuredarticles/ViewControllerPGforiPhoneOS/BuildinganAdaptiveInterface.html#//apple_ref/doc/uid/TP40007457-CH32-SW2) 。 * **避免使用特有信息来做出关于界面布局或内容的决定**。在 iPad 和 iPhone 上运行的应用程序通常应显示相同的信息,应使用 Size class 来进行布局决策。 ### 第二节 什么时候特征和 Size 发生变化? 特征变化很少发生,但确实发生。UIKit 根据底层环境的变化更新视图控制器的特性。Size class 的特征比显示比例特征更有可能发生变化。成语的特点的改变有的话应该也很少。 Size class更改发生的原因如下: * 视图控制器窗口的垂直或水平 Size class 通常由于设备旋转而改变。 * 容器视图控制器的水平或垂直 Size class 已更改。 * 当前视图控制器的水平或垂直 Size class由其容器显式更改。 视图控制器层次结构中的 Size class 更改传播到任何子视图控制器。 窗口对象作为该层次结构的根节点,为其根视图控制器提供基线 Size class 特征。 当设备方向在纵向和横向之间变化时,窗口会更新自己的 Size class 信息,并沿着视图控制器层次结构传播该信息。 容器视图控制器可以将更改传递给未经修改的子视图控制器,也可以覆盖每个子视图的特征。 在 iOS 8 和以后的版本中,窗口的原点总是在左上角,当设备在横向和纵向之间旋转时,窗口的边界会发生变化。窗口大小的变化会沿着视图控制器的层级传播,并伴随着相应的特征改变。对于层次结构中的每个视图控制器,UIKit 调用下面的方法来报告这些变化: * [willTransitionToTraitCollection:withTransitionCoordinator:](https://developer.apple.com/documentation/uikit/uicontentcontainer/1621511-willtransitiontotraitcollection) 告诉每个相关的视图控制器,它的特征即将改变。 * [viewWillTransitionToSize:withTransitionCoordinator:](https://developer.apple.com/documentation/uikit/uicontentcontainer/1621466-viewwilltransitiontosize) 告诉每个相关的视图控制器它的大小即将改变。 * [ traitCollectionDidChange:](https://developer.apple.com/documentation/uikit/uitraitenvironment/1623516-traitcollectiondidchange) 告诉每个相关的视图控制器, 它的特征现在已经改变了。 遍历视图控制器层次结构时,UIKit 只有在发生更改时才会将更改报告给视图控制器。 如果容器视图控制器重写其子节点的 Size class,则在容器的 Size class 更改时不会通知这些子节点。同样,如果一个视图控制器的视图有一个固定的宽度和高度,它不会收到 Size class 更改通知。 图 12-2 显示了在 iPhone 6 上发生旋转时视图控制器的特性和视图大小是如何更新的。从纵向到横向的旋转改变了屏幕的垂直大小,从常规到紧凑。Size class 的改变和相应的视图大小的改变将被传播到视图控制器层次结构中。将视图动画到为新 Size 后,UIKit 在调用视图控制器的 [ traitCollectionDidChange:](https://developer.apple.com/documentation/uikit/uitraitenvironment/1623516-traitcollectiondidchange) 方法之前应用 Size class 和视图 Size 更改。 ###### 图 12-2 更新视图控制器的特征和视图 size ![](https://developer.apple.com/library/content/featuredarticles/ViewControllerPGforiPhoneOS/Art/VCPG_RotationTraits_fig_13-2_2x.png) ### 第三节 不同设备的默认 Size Classes 每个iOS设备都有一组默认的 Size Class,可以在设计界面时使用它们作为参考指南。表 12-2 列出了纵向和横向两种设备的 Size Class 未在表格中列出的设备与具有相同屏幕尺寸的设备具有相同的 Size Class 。 ###### 表 12-2 不同屏幕尺寸的设备的 Size Classes ![](https://box.kancloud.cn/63fe65c8780da669485dc993b1390e86_1708x758.png) > 重要提示 切勿假设您的应用程序将在设备上显示特定的 Size Class 。 在决定如何配置对象时,总是检查对象特征集合中找到的 Size Class 。