在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编辑效果如下:

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

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

    Size Classes with Xcode 6: One Storyboard for all Sizes 为所有的尺寸准备一个Storyboard 我最喜欢的Xcode6的特性是新的size c ...

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

    我最喜欢的Xcode6的特性是新的size classes 概念,有了它,我们解决了“我如何能够快速的为那么多不同尺寸屏幕以及方向的设备写app”.他们也让在一个storyboard中创建一个通用的a ...

  3. iOS:Size Classes的使用

    iOS 8在应用界面的可视化设计上添加了一个新的特性-Size Classes,对于任何设备来说,界面的宽度和高度都只分为两种描述:正常和紧凑.这样开发者便可以无视设备具体的尺寸,而是对这两类和它们的 ...

  4. Swift - 使用Auto Layout和Size Classes实现页面自适应弹性布局

    在过去只有iphone4的时候,可以在代码里将一个可视单元的位置写死,这样是没问题的,但随着iPhone5,6的发布,屏幕尺寸有了越来越多种可能.这就要求App的UI控件具有在不同屏幕尺寸的设备上具有 ...

  5. Xcode 6 AutoLayout Size Classes

    1.基本概念 在iPad和iPhone 5出现之前,iOS设备就唯独一种尺寸. 我们在做屏幕适配时须要考虑的唯独设备方向而已. 而非常多应用并不支持转向,这种话就全然没有屏幕适配的工作了. 随着iPa ...

  6. 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 diffe ...

  7. Size Classes with Xcode 6

    转载自 http://www.cocoachina.com/ios/20141015/9919.html 总结:通过在Size Classes不同的模式下设置,可以实现不同设备在横屏.竖屏下UIVie ...

  8. 关于IOS的屏幕适配(iPhone)——Auto Layout和Size Classes

    Auto Layout和Size Classes搭配使用极大的方便了开发者,具体如何使用Auto Layout和Size Classes大家可以参考其他文章或者书籍,这里只提一点,在我们设置Size ...

  9. iOS Autoresizing Autolayout Size classes

    Autoresizing:出现最早,仅仅能够针对父控件做约束(注意:要关闭Autolayout&Size classes才能够看到Autoresizing) 代码对应: UIView.h中的a ...

随机推荐

  1. (转)Python JSON序列化

    import json # dict to json d=dict(name="cui",age=20,score=88) print json.dumps(d) #list to ...

  2. fstream对象重复使用时注意clear()的调用

    fstream对象重复使用时注意clear()的调用,否则会造成打开第二个文件失败.这是因为一个fstream对象对应磁盘上的一个文件,这种绑定关系在调用open()函数或者构造函数时指定,但有时我们 ...

  3. CS小分队第一阶段冲刺站立会议(5月8日)

    昨日成果:优化了扫雷游戏,解决了界面随格子数改变却不能缩小的bug,另外改写了程序,能使用户在点下第一个雷时再生成代码,防止第一步踩到地雷. 遇到的困难:主要就是考虑扫雷需不需要有一个存档,这个存档用 ...

  4. Oracle VM VirtualBox 5.0 CentOS 6.4 共享文件夹

    首先在主机(win7)的硬盘建立需要共享文件夹 例如 D:\share_test 然后虚拟机光驱加载Oracle VM VirtualBox安装目录的iso  C:\Program Files\Ora ...

  5. STL容器的适用情况

     转自http://hsw625728.blog.163.com/blog/static/3957072820091116114655254/ ly; mso-default-props:yes; m ...

  6. 三分--Football Goal(面积最大)

    B - Football Goal Time Limit:500MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u Su ...

  7. [工作记录] Android OpenGL ES: non-square texture - continue

    previous: [工作记录] Android OpenGL ES 2.0: square texture not supported on some device recently I found ...

  8. Oracle 显示时间问题

    在部署的时候. 显示的时间为会 2014/1/1 9:00:00 pm   但开发过程中显示为正常: 2014-1-1 21:00:00   解决方法: 1. Oracle数据库的时间格式没有问题, ...

  9. Javascript在页面加载时的执行顺序【转】

    一.在HTML中嵌入Javasript的方法 直接在Javascript代码放在标记对<script>和</script>之间 由<script />标记的src属 ...

  10. DOS永久设置系统环境变量-WMIC

    wmic Windows Management Instrumentation Command-line(Windows管理规范命令行) WMIC扩展WMI(Windows Management In ...