Xcode 6 AutoLayout Size Classes
1、基本概念
在iPad和iPhone 5出现之前,iOS设备就唯独一种尺寸。
我们在做屏幕适配时须要考虑的唯独设备方向而已。
而非常多应用并不支持转向,这种话就全然没有屏幕适配的工作了。
随着iPad和iPhone 5。以及接下来的iPhone 6的推出,屏幕尺寸也变成了须要考虑的对象。在iOS7之前,为一个应用。特别是universal的应用制作UI时,我们总会首先想我们的目标设备的长宽各是多少。方向变换以后布局又应该怎么改变,然后进行布局。
iOS6引入了AutoLayout来帮助开发人员使用约束进行布局,这使得在某些情况下我们不再须要考虑尺寸,而能够专注于使用约束来规定位置。
既然我们有了AutoLayout,那么事实上通过约束来指定视图的位置和尺寸是没有什么问题的了。从这个方面来说,屏幕的详细的尺寸和方向已经不那么重要了。可是实战中这还不够。AutoLayout正如其名,仅仅是一个依据约束来进行布局的方案。而在相应不同设备的详细情况下的体验上还有欠缺。一个最明显的问题是它不能依据设备类型来确定不同的交互体验。非常多时候你还是须要推断设备究竟是iPhone还是iPad。以及如今的设备方向究竟是竖直还是水平来做出推断。
这种话我们还是难以彻底摆脱对于设备的推断和依赖,而之后假设有新的尺寸和设备出现的话。这种依赖关系显然显得十分脆弱的(想想要是有iWatch的话..)。
所以在iOS8里,Apple从最初的设计哲学上将原来的方式推翻了。并引入了一整套新的理念,来适应设备不断的发展。这就是SizeClasses。
不再依据设备屏幕的详细尺寸来进行区分。而是通过它们的感官表现,将其分为普通(Regular)和紧密(Compact)两个种类(class)。开发人员便能够无视详细的尺寸,而是对这这两类和它们的组合进行适配。这样不论在设计时还是代码上。我们都能够不再受限于详细的尺寸,而是变成遵循尺寸的视觉感官来进行适配。
SizeClasses有三个值:Regular,Compact和Any。
Any是什么意思呢?假设weight设为Any,height设置为Regular,那么在该状态下的界面元素在仅仅要height为Regular,不管weight是Regular还是Compact的状态中都会存在。这样的关系应该叫做继承关系。详细的四种界面描写叙述与可继承的界面描写叙述例如以下:
1
2
3
4
|
w:Compacth:Compact继承(w:Anyh:Compact,w:Compacth:Any,w:Anyh:Any) w:Regularh:Compact继承(w:Anyh:Compact,w:Regularh:Any,w:Anyh:Any) w:Compacth:Regular继承(w:Anyh:Regular,w:Compacth:Any,w:Anyh:Any) w:Regularh:Regular继承(w:Anyh:Regular,w:Regularh:Any,w:Anyh:Any) |
这么多设备(iPhone 4S,iPhone 5/5s,iPhone 6,iPhone 6Plus,iPad,AppleWatch)的尺寸。就通过SizeClasses简单的表达出来了:
iPhone4S,iPhone 5/5s,iPhone 6
竖屏:(w:Compacth:Regular)
横屏:(w:Compacth:Compact)
iPhone6Plus
竖屏:(w:Compacth:Regular)
横屏:(w:Regularh:Compact)
iPad
竖屏:(w:Regularh:Regular)
横屏:(w:Regularh:Regular)
AppleWatch(推測)
竖屏:(w:Compacth:Compact)
横屏:(w:Compacth:Compact)
PS:附上图形:
2、UITraitCollection和UITraitEnvironment(Size Classes手写代码)
为了表征SizeClasses。Apple在iOS 8中引入了一个新的类。UITraitCollection。
这个类封装了像水平和竖直方向的SizeClass等信息。iOS 8的UIKit中大多数UI的基础类(包含UIScreen。UIWindow。UIViewController和UIView)都实现了UITraitEnvironment这个接口。通过当中的traitCollection这个属性。我们能够拿到相应的UITraitCollection对象。从而得知当前的SizeClass,并进一步确定界面的布局。
和UIKit中的响应者链正好相反。traitCollection将会在viewhierarchy中自上而下地进行传递。对于没有指定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
|
override func willTransitionToTraitCollection(newCollection: UITraitCollection, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator){ super .willTransitionToTraitCollection(newCollection, withTransitionCoordinator: coordinator) coordinator.animateAlongsideTransition({ (context: UIViewControllerTransitionCoordinatorContext!) -> Void in if (newCollection.verticalSizeClass == UIUserInterfaceSizeClass.Compact) { //To Do: modify something for compact vertical size } else { //To Do: modify something for other vertical size } self.view.setNeedsLayout() }, completion: nil) } |
在两个To Do中,我们应该删除或者加入或者更改不同条件下的AutoLayout约束(当然,你也能够干其它不论什么你想做的事情),然后调用-setNeedsLayout来在上下文中触发转移动画。
假设你坚持用代码来处理的话,可能须要面临对于不同SizeClasses来做移除旧的约束和加入新的约束这种事情,能够说是非常麻烦(至少我认为是麻烦的要死)。
可是假设我们使用IB的话,这些事情和代码都能够省掉。我们能够非常方便地在IB中指定各种SizeClasses的约束(稍后会介绍怎样使用IB来相应SizeClasses)。另外使用IB不仅能够节约成百上千行的布局代码。更能够从新的Xcode和IB中得到非常多设计时就能够实时监视,查看而且调试的特性。能够说手写UI和使用IB设计的时间消耗和成本差距被进一步拉大,而且出现了非常多手写UI无法实现。可是IB能够不假思索地完毕的任务。从这个意义上来说。新的IB和SizeClasses系统能够说无情地给手写代码判了个死缓。
另外,新的API和体系的引入也同一时候给非常多我们熟悉的UIViewController的有关旋转的老朋友判了死刑,比方以下这些API都弃用了:
1
2
3
4
5
6
|
@property(nonatomic, readonly) UIInterfaceOrientation interfaceOrientation - willRotateToInterfaceOrientation:duration: - willAnimateRotationToInterfaceOrientation:duration: - didRotateFromInterfaceOrientation: - shouldAutomaticallyForwardRotationMethods |
如今所有统一到了viewWillTransitionToSize:withTransitionCoordinator:,旋转的概念不再被提倡使用。事实上细致想想。所谓旋转,只是就是一种Size的改变而已,我们都被Apple骗了好多年,不是么?
3、InterfaceBuilder中使用SizeClasses
创建一个新的通用项目。假设你想要早在一个已经创建了的Xcode6项目,你须要激活sizeclasses选项。你能够在InterfaceBuilder中的属性面板勾选autolayout的选项的以下找到它。
首先。让我们在Xcode中看一下sizeclass的网格。这是一个你能够在不同的布局排列间切换的区域。
当你查看storyboard的时候,看到视图的底部,而且点击‘wAnyhAny’字样的标签。
你将会看到一些类似网格的画面。
默认的,我们以一个基础的设置開始,也就是anywidth和anyheight。
非常多事情都将在这里安置和改变,包含了iphone和ipad的全部方向的默认布局。苹果建议把大多数的设置都在这个界面中进行设置。
这个是由于降低工作量而显得特别的简单。让我们布局一个超级宽的button在画面的中间。
给它一个绿色的背景,从而让我们看到它真实的尺寸,给它一个约束来让他居中。
而且给它一个夸张的固定宽度600。
好了,如今在ipad和iphone的模拟器都执行一下。你将会看到都是居中,但对于iphone的两个方向都太宽了,(这里你设置了页面中button的宽度但并没有立即更新是由于你在做加入约束的时候没有更新图形,导致了例如以下图的情况,storyboard里面没有更新,而在模拟器执行时候更新了,左边大纲栏目里面也有警告说明,能够直接点击警告里面的黄色三角来更新画面事实上就是UpdataFrame)
让我们使用sizeclasses来修正吧。
回到刚才那个第一张图的网格选择iphone的纵向(portrait)设置,就是紧凑的宽度+常规的高度。网格中的红色矩形.
你将会注意到你在网格中选中之后底部的bar改变为蓝色。那是在警告你:“Hey,你并非在一个基础的设置。有些改变将会仅仅在你执行的时候显示。所以这个bar如今是蓝色的!”我所说的一些改变是由于有四项你能改变的sizeclasses:1约束常数。2字体。3约束的开/关,4子视图的开/关。
前两个是不言而喻的,可是让我来告诉你怎样让后两者工作。在当前的sizeclass(compactwidth和regularheight)状况下让我们试着把一个约束关闭。在文档的提纲栏里,点击设置在我们的button的CentreX校准约束:
如今看一下我们的属性检查栏,在底部我们能够看到带标记的一个单词“Installed”,而且左側有额外的加号button。点击额外的加号而且点选'CompactWidth|RegularHeight'(当前的就是)。
如今你将会看到2个标记物,把刚刚加入的哪一个取消勾选(wChR)
如今我们的约束不再安置而且做不论什么事情来配置sizeclasses。
就像你看到的,Xcode正在控诉我们的约束太混乱了(左边的大纲会有错误提示表示你缺少了约束-译者)。假设你这时候执行app在iphone的模拟器上的话,按钮不在X方向居中了。
可是在ipad的上面还是居中的。由于约束仍然安置在主要的设置里面。这个约束将会一直配置着除非我们把它取消勾选。
你甚至可以旋转你的iphone模拟器,而且发现button将会奇妙的回到居中,由于iphone的横向是不同的sizeclass配置。好了,让我们把勾选回来。让button回到居中。
如今让我们改变我们设置在button宽度的约束,选择button。而且来到Size的属性检查栏,下拉究竟部,我们能够看到全部的约束。点击Width原本是600的使用Edit设置为100:
在iPhone的模拟器上执行,你将会看到button已经具备了正确的宽度。
执行在ipad的模拟器的时候却展示了600的宽度,由于我们没有改变基本设置里面的宽度。可是,在iphone的横向landscape仍然看着不怎么样。由于iphone的横向设置来自主要的AnyAny的设置。
让我们修正一下。
在网格里面我们选择compactWidth和CompactHeight。也就是第一张图的蓝色网格。
如今我们在这个设置下改变width的约束,就像我们为了compactxregular改变的一样。给予一个400的宽度。
执行一下iphone的模拟器。而且旋转到横向。button有了400的宽度,看上去非常棒。
达到了我们的预想。有一点非常好就是你能看到一个全部的约束的列表。这些都是不同的设置的。只选择你想要在文档大纲里面看到的约束,然后来到属性检查栏。他们整齐的排列在初始的常数以下。它标注了每个基于它所应用的设置。
即使我们决定我们想要仅仅在iphone横向landscape模式下button消失。使用sizeclasses我们仅仅要反向安置views就像我们反向安置一个约束。选择我们的UIbutton,滚动到属性检查器的底部。
通过点击加号按钮给我们当前的设置加入一个新的安置选项。然后取消勾选它。
就像你看到的,那个view立刻消失了。由于我们在设置里面反向安置了它。我们立刻就能看到。执行app。你能看到它在纵向的portraitiphone上消失了,可是当你旋转到横向的landscape的时候又回来了。
当然它也一直安置在ipad上面由于ipad仍然使用的是主要的设置。
4、SizeClasses和ImageAsset及UIAppearence
ImageAsset里也加入了对SizeClasses的支持。也就是说。我们能够对不同的SizeClass指定不同的图片了。在ImageAsset的编辑面板中选择某张图片。Inspector里如今多了一个Width和Height的组合,加入我们须要相应的SizeClass,然后把合适的图拖上去。这样在执行时SDK就将从中挑选相应的Size的图进行替换了。不仅如此,在IB中我们也能够选择相应的size来直接在编辑时查看变化。
实际做起来实在是太简单了..但拿个demo说明一下吧,比方以下这个实现了竖直方向Compact的时候将笑脸换成哭脸--当然了,一行代码都不须要。
另外,在iOS7中UIImage加入了一个renderingMode属性。我们能够使用imageWithRenderingMode:并传入一个合适的UIImageRenderingMode来指定这个image要不要以Template的方式进行渲染。在新的Xcode中,我们能够直接在ImageAsset里的RenderAs选项来指定是不是须要作为template使用。而对应的,在UIApperance中,Apple也为我们对于SizeClasses加入了对应的方法。
使用+appearanceForTraitCollection:方法,我们就能够针对不同trait下的应用的apperance进行非常easy的设定。
比方在上面的样例中。我们想让笑脸是绿色,而哭脸是红色的话。不要太简单。首先在ImageAsset里的渲染选项设置为TemplateImage,然后直接在AppDelegate里加上这样两行:
1
2
|
UIView.appearanceForTraitCollection(UITraitCollection(verticalSizeClass:.Compact)).tintColor=UIColor.redColor() UIView.appearanceForTraitCollection(UITraitCollection(verticalSizeClass:.Regular)).tintColor=UIColor.greenColor() |
完毕,仅仅只是拖拖鼠标。两个代码简单的线条,那么颜色的变化可以庆幸,这真的是一个伟大的事情一大快所有的人。
版权声明:本文博客原创文章,博客,未经同意,不得转载。
Xcode 6 AutoLayout Size Classes的更多相关文章
- iOS Autoresizing Autolayout Size classes
Autoresizing:出现最早,仅仅能够针对父控件做约束(注意:要关闭Autolayout&Size classes才能够看到Autoresizing) 代码对应: UIView.h中的a ...
- [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 ...
- Size Classes with Xcode 6:为所有的尺寸准备一个Storyboard
我最喜欢的Xcode6的特性是新的size classes 概念,有了它,我们解决了“我如何能够快速的为那么多不同尺寸屏幕以及方向的设备写app”.他们也让在一个storyboard中创建一个通用的a ...
- Size Classes with Xcode 6
转载自 http://www.cocoachina.com/ios/20141015/9919.html 总结:通过在Size Classes不同的模式下设置,可以实现不同设备在横屏.竖屏下UIVie ...
- iOS:Size Classes的使用
iOS 8在应用界面的可视化设计上添加了一个新的特性-Size Classes,对于任何设备来说,界面的宽度和高度都只分为两种描述:正常和紧凑.这样开发者便可以无视设备具体的尺寸,而是对这两类和它们的 ...
- iOS8 Size Classes的理解与使用
在iOS8中,新增了Size Classes特性,它是对当前所有iOS设备尺寸的一个抽象,也是该抽象了,想想现在多少种iOS尺寸的设备吧:iPhone4-5-6-6plus.iPad.iPad min ...
- 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 ...
- Swift - 使用Auto Layout和Size Classes实现页面自适应弹性布局
在过去只有iphone4的时候,可以在代码里将一个可视单元的位置写死,这样是没问题的,但随着iPhone5,6的发布,屏幕尺寸有了越来越多种可能.这就要求App的UI控件具有在不同屏幕尺寸的设备上具有 ...
- 关于IOS的屏幕适配(iPhone)——Auto Layout和Size Classes
Auto Layout和Size Classes搭配使用极大的方便了开发者,具体如何使用Auto Layout和Size Classes大家可以参考其他文章或者书籍,这里只提一点,在我们设置Size ...
随机推荐
- python实现了字符串的按位异或和php中的strpad函数
近期在写自己主动化測试,因为开发加密中用到strpad和字符串的按位异或,而python中没有这种函数和功能,所以必须自己写一套,要不自己主动化測试无法进行,所以就用python实现了一下,因为在写字 ...
- 2014鞍山现场赛C题HDU5072(素筛+容斥原理)
Coprime Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others) Total ...
- ArrayList线程不安全?
ArrayList是线程不安全的,轻量级的.如何使ArrayList线程安全? 1.继承Arraylist,然后重写或按需求编写自己的方法,这些方法要写成synchronized,在这些synchro ...
- 为了找到自己的路——leo锦书62
<Leo锦书(文章1编辑)>百度已经降落阅读,今后将继续更新.免费下载:http://t.cn/RvawZEx 柯克•卡梅隆是谁呢?在中国听过这名字的人预计不多.但看下封面我们马下就会说: ...
- Python重写C语言程序100例--Part6
''' [程序41] 题目:学习static定义静态变量的使用方法 1.程序分析: 2.程序源码: ''' # python没有这个功能了,仅仅能这样了:) def varfunc(): var = ...
- HTML——UL+CSS设计
截图例如,下面的: <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/ ...
- 逆向project第004篇:令计算器程序显示汉字(下)
一.前言 钩子技术是一项很有有用价值的技术.在Windows下HOOK技术的方法比較多,使用比較灵活,常见的应用层的HOOK方法有Inline HOOK(详见<反病毒攻防研究第012篇:利用In ...
- 用bytecode来看try-catch-finally和return
之前看过一篇关于return和finally运行顺序的文章.仅在Java的语言层面做了分析.事实上我倒认为直接看bytecode可能来的更清晰一点. 近期一直在看Java虚拟机规范.发现直接分析byt ...
- socket用法
INADDR_ANY是ANY,是绑定地址0.0.0.0上的监听, 能收到任意一块网卡的连接:INADDR_LOOPBACK, 也就是绑定地址LOOPBAC, 往往是127.0.0.1, 只能收到127 ...
- CentOS 6.4 文件夹打开方式
CentOS 6.4 文件夹打开方式 在CentOS 6.4中,双击文件夹,默认会在新窗口中打开文件夹,没有路径.前进.后退这样的按钮,如果一个文件夹的路径很深,则需要打开n多的窗口才能找到最终想要的 ...