iOS8 Size Classes的理解与使用

在iOS8中,新增了Size Classes特性,它是对当前所有iOS设备尺寸的一个抽象,也是该抽象了,想想现在多少种iOS尺寸的设备吧:iPhone4-5-6-6plus、iPad、iPad mini、iWatch,如何还是按照以前那针对种特定设备来编写不同的布局的话,一定是很糟糕的一件事情。

现在有了sizeclass,事情就好办多了:你不是设备多吗,那我们就只把屏幕的宽和高分别分成三种情况:(Compact, Regular, Any),也即紧凑、正常和任意。这样宽和高三三一整合,一共9中情况。如下图所示,针对每一种情况,如果需要的话,我们可以单独在storyboard或xib中设置UIView的自动布局约束,甚至某一个button是否显示都是能轻松实现。

和 UIKit 中的响应者链正好相反,traitCollection 将会在 view hierarchy 中自上而下地进行传递。对于没有指定 traitCollection 的 UI 部件,将使用其父节点的 traitCollection。这在布局包含 childViewController 的界面的时候会相当有用。在 UITraitEnvironment 这个接口中另一个非常有用的是 -traitCollectionDidChange:。在 traitCollection 发生变化时,这个方法将被调用。在实际操作时,我们往往会在 ViewController 中重写 -traitCollectionDidChange: 或者 -willTransitionToTraitCollection:withTransitionCoordinator: 方法 (对于 ViewController 来说的话,后者也许是更好的选择,因为提供了转场上下文方便进行动画;但是对于普通的 View 来说就只有前面一个方法了),然后在其中对当前的 traitCollection 进行判断,并进行重新布局以及动画。代码看起来大概会是这个样子:

  1. - (void)willTransitionToTraitCollection:(UITraitCollection *)newCollection
  2. withTransitionCoordinator:(id <UIViewControllerTransitionCoordinator>)coordinator
  3. {
  4. [super willTransitionToTraitCollection:newCollection
  5. withTransitionCoordinator:coordinator];
  6. [coordinator animateAlongsideTransition:^(id <UIViewControllerTransitionCoordinatorContext> context) {
  7. if (newCollection.verticalSizeClass == UIUserInterfaceSizeClassCompact) {
  8. //To Do: modify something for compact vertical size
  9. } else {
  10. //To Do: modify something for other vertical size
  11. }
  12. [self.view setNeedsLayout];
  13. } completion:nil];
  14. }

在两个 To Do 中,我们应该删除或者添加或者更改不同条件下的 Auto Layout 约束 (当然,你也可以干其他任何你想做的事情),然后调用 -setNeedsLayout 来在上下文中触发转移动画。如果你坚持用代码来处理的话,可能需要面临对于不同 Size Classes 来做移除旧的约束和添加新的约束这样的事情,可以说是很麻烦 (至少我觉得是麻烦的要死)。但是如果我们使用 IB 的话,这些事情和代码都可以省掉,我们可以非常方便地在 IB 中指定各种 Size Classes 的约束 (稍后会介绍如何使用 IB 来对应 Size Classes)。另外使用 IB 不仅可以节约成百上千行的布局代码,更可以从新的 Xcode 和 IB 中得到很多设计时就可以实时监视,查看并且调试的特性。可以说手写 UI 和使用 IB 设计的时间消耗和成本差距被进一步拉大,并且出现了很多手写 UI 无法实现,但是 IB 可以不假思索地完成的任务。从这个意义上来说,新的 IB 和 Size Classes 系统可以说无情地给手写代码判了个死缓。

另外,新的 API 和体系的引入也同时给很多我们熟悉的 UIViewController 的有关旋转的老朋友判了死刑,比如下面这些 API 都弃用了:

  1. @property(nonatomic, readonly) UIInterfaceOrientation interfaceOrientation
  2. - willRotateToInterfaceOrientation:duration:
  3. - willAnimateRotationToInterfaceOrientation:duration:
  4. - didRotateFromInterfaceOrientation:
  5. - shouldAutomaticallyForwardRotationMethods

现在全部统一到了 viewWillTransitionToSize:withTransitionCoordinator:,旋转的概念不再被提倡使用。其实仔细想想,所谓旋转,不过就是一种 Size 的改变而已,我们都被 Apple 骗了好多年,不是么?

在Xcode中的具体体现如下图:

但是我们看到图中的宽度和高度都是Any,Any是什么意思呢?如果weight设为Anyheight设置为Regular,那么在该状态下的界面元素在只要heightRegular,无论weightRegular还是Compact的状态中都会存在。这种关系应该叫做继承关系,具体的四种界面描述与可继承的界面描述如下:

  • w:Compact h:Compact 继承 (w:Any h:Compact , w:Compact h:Any , w:Any h:Any)
  • w:Regular h:Compact 继承 (w:Any h:Compact , w:Regular h:Any , w:Any h:Any)
  • w:Compact h:Regular 继承 (w:Any h:Regular , w:Compact h:Any , w:Any h:Any)
  • w:Regular h:Regular 继承 (w:Any h:Regular , w:Regular h:Any , w:Any h:Any)

我们知道了iOS 8下面设备界面可以描述为4种,但是这么多设备(iPhone4S,iPhone5/5s,iPhone6,iPhone6 Plus,iPad,Apple Watch)具体对应什么描述呢?经过查看官方文档和具体实践得知具体对应关系如下:

  • iPhone4S,iPhone5/5s,iPhone6

    • 竖屏:(w:Compact h:Regular)
    • 横屏:(w:Compact h:Compact)
  • iPhone6 Plus
    • 竖屏:(w:Compact h:Regular)
    • 横屏:(w:Regular h:Compact)
  • iPad
    • 竖屏:(w:Regular h:Regular)
    • 横屏:(w:Regular h:Regular)
  • Apple Watch(猜测)
    • 竖屏:(w:Compact h:Compact)
    • 横屏:(w:Compact h:Compact)

Size Classes手写代码

为了表征Size Classes,Apple在iOS8中引入了一个新的类,UITraitCollection。这个类封装了像水平和竖直方向的Size Class等信息。iOS8的UIKit中大多数UI的基础类(包括UIScreen,UIWindow,UIViewController和UIView)都实现了UITraitEnvironment这个接口,通过其中的traitCollection这个属性,我们可以拿到对应的UITraitCollection对象,从而得知当前的Size Class,并进一步确定界面的布局。和UIKit中的响应者链正好相反,traitCollection将会在view hierarchy中自上而下地进行传递。对于没有指定traitCollection的UI部件,将使用其父节点的traitCollection。这在布局包含childViewController的界面的时候会相当有用。在UITraitEnvironment这个接口中另一个非常有用的是-traitCollectionDidChange:。在traitCollection发生变化时,这个方法将被调用。在实际操作时,我们往往会在ViewController中重写-traitCollectionDidChange:或者-willTransitionToTraitCollection:withTransitionCoordinator:方法(对于ViewController来说的话,后者也许是更好的选择,因为提供了转场上下文方便进行动画;但是对于普通的View来说就只有前面一个方法了),然后在其中对当前的traitCollection进行判断,并进行重新布局以及动画。代码看起来大概会是这个样子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
- (void)willTransitionToTraitCollection:(UITraitCollection *)newCollection
              withTransitionCoordinator:(id <UIViewControllerTransitionCoordinator>)coordinator
{
    [super willTransitionToTraitCollection:newCollection
                 withTransitionCoordinator:coordinator];
    [coordinator animateAlongsideTransition:^(id <UIViewControllerTransitionCoordinatorContext> context)
    {
        if (newCollection.verticalSizeClass == UIUserInterfaceSizeClassCompact) {
            //To Do: modify something for compact vertical size
        } else {
            //To Do: modify something for other vertical size
        }
        [self.view setNeedsLayout];
    } completion:nil];
}

在两个To Do处,我们要手写代码针对不同的状态做调整。

Size Classes与Interface Builder

Xcode6中Interface BuilderSize Class有了很强大的支持,xib中可以开启Size Classes如下图:

在不同的Size Classes描述下,界面元素可以选择安装还是不安装,具体操作如图:

Size Classes与Image Asset

Xcode6中Image Asset也支持了Size Class,也就是说,我们可以对不同的Size Class指定不同的图片了。在Image Asset的编辑面板中选择某张图片,Inspector里现在多了一个WidthHeight的组合,添加我们需要对应的Size Class,然后把合适的图拖上去,这样在运行时SDK就将从中挑选对应的Size的图进行替换了。支持Size ClassImage Asset编辑效果如下:

时间: 2024-08-27 07:53:00

iOS8 Size Classes的理解与使用的相关文章

【iOS开发-120】在storyboard中如何使用Size Classes,其实就是设置多套AutoLayout

(1)在storyboard中使用Size Classes. 我们之前使用过AutoLayout,目前多了一个Size Classes,可以看做是在不同的Size Classes下进行AutoLayout设置. 详细教程,http://www.cocoachina.com/ios/20141020/9978.html --貌似,storyboard的功能越来越强大了.光是不同尺寸和屏幕的适配,就足以让敲代码成为一种痛苦. --找了很多博文,发现,几乎都是谈如何在storyboard中使用Size

Size Classes with Xcode 6:为所有的尺寸准备一个Storyboard

我最喜欢的Xcode6的特性是新的size classes 概念,有了它,我们解决了“我如何能够快速的为那么多不同尺寸屏幕以及方向的设备写app”.他们也让在一个storyboard中创建一个通用的app.通过与新的适应屏幕的controller联合,它能够更简单的依靠interface builder,而不是与之对抗,从而简化了你应用的布局. 应用中的每一个view controller 都有一个特别的collection对象,这个特别的collection对象都有两个size classes

Size Classes with Xcode 6&lt;转&gt;

1.基本概念 在iPad和iPhone 5出现之前,iOS设备就只有一种尺寸.我们在做屏幕适配时需要考虑的仅仅有设备方向而已.而很多应用并不支持转向,这样的话就完全没有屏幕适配的工作了.随着iPad和iPhone 5,以及接下来的iPhone 6的推出,屏幕尺寸也变成了需要考虑的对象.在iOS7之前,为一个应用,特别是universal的应用制作UI时,我们总会首先想我们的目标设备的长宽各是多少,方向变换以后布局又应该怎么改变,然后进行布局.iOS6引入了AutoLayout来帮助开发者使用约束

[IOS]译Size Classes with Xcode 6: One Storyboard for all Sizes

Size Classes with Xcode 6: One Storyboard for all Sizes 为所有的尺寸准备一个Storyboard 我最喜欢的Xcode6的特性是新的size classes 概念,有了它,我们解决了“我如何能够快速的为那么多的不同尺寸屏幕以及方向的设备写app”.他们也让在一个storyboard中创建一个通用的app.通过与新的适应屏幕的controller联合,它能够更简单的依靠interface builder,而不是与之对抗,从而简化了你应用的布局

Xcode 6 AutoLayout Size Classes

1.基本概念 在iPad和iPhone 5出现之前,iOS设备就只有一种尺寸.我们在做屏幕适配时需要考虑的仅仅有设备方向而已.而很多应用并不支持转向,这样的话就完全没有屏幕适配的工作了.随着iPad和iPhone 5,以及接下来的iPhone 6的推出,屏幕尺寸也变成了需要考虑的对象.在iOS7之前,为一个应用,特别是universal的应用制作UI时,我们总会首先想我们的目标设备的长宽各是多少,方向变换以后布局又应该怎么改变,然后进行布局.iOS6引入了AutoLayout来帮助开发者使用约束

Size Classes with Xcode 6

1.基本概念 在iPad和iPhone 5出现之前,iOS设备就只有一种尺寸.我们在做屏幕适配时需要考虑的仅仅有设备方向而已.而很多应用并不支持转向,这样的话就完全没有屏幕适配的工作了.随着iPad和iPhone 5,以及接下来的iPhone 6的推出,屏幕尺寸也变成了需要考虑的对象.在iOS7之前,为一个应用,特别是universal的应用制作UI时,我们总会首先想我们的目标设备的长宽各是多少,方向变换以后布局又应该怎么改变,然后进行布局.iOS6引入了AutoLayout来帮助开发者使用约束

Asset Catalog Help (七)---Customizing Image Sets for Size Classes

Customizing Image Sets for Size Classes Add images to a set that are customized for display in different size classes supported by your app. 应用程序也支持把图片存入一个自定义集合,用来在不同的尺寸类中显示. In the set list, select an image set. 在集合列表(set list)中,选择一个图片集. Open the ut

iOS Autoresizing Autolayout Size classes

Autoresizing:出现最早,仅仅能够针对父控件做约束(注意:要关闭Autolayout&Size classes才能够看到Autoresizing) 代码对应: UIView.h中的autoresizingMask属性 @property(nonatomic) UIViewAutoresizing autoresizingMask;    // simple resize. default is UIViewAutoresizingNone typedef NS_OPTIONS(NSUI

iOS Xcode6 AutoLayout跟Size Classes(4)size classes 的应用

iOS 8在应用界面的可视化设计上添加了一个新的特性-Size Classes,对于任何设备来说,界面的宽度和高度都只分为两种描述:正常和紧凑.这样开发者便可以无视设备具体的尺寸,而是对这两类和它们的组合进行适配.这样不论在设计时还是代码上,我们都可以不再受限于具体的尺寸,而是变成遵循尺寸的视觉感官来进行适配 要知道Size Classes并不能帮我们自动布局,而是帮助我们来管理不同类型的IB 但是我们看到图中的宽度和高度都是Any,Any是什么意思呢?如果weight设为Any,height设