http://blog.sina.com.cn/s/blog_693de6100102v4sl.html
关于AutoLayout,最早从iOS6开始引入使用。
主要功能是使用约束,对视图进行相对布局,以适应不同屏尺的变换。
网上大量的资料都在介绍xib和storyboard,如何使用AutoLayout,说纯代码使用AutoLayout进行UI布局的越来越少。对于我这个习惯了代码UI布局的人,写个备忘:
AutoLayout是什么?
使用一句Apple的官方定义的话 关键词:- 基于约束 - 和以往定义frame的位置和尺寸不同,AutoLayout的位置确定是以所谓相对位置的约束来定义的,比如x坐标为superView的中心,y坐标为屏幕底部上方10像素等
- 描述性 - 约束的定义和各个view的关系使用接近自然语言或者可视化语言(稍后会提到)的方法来进行描述
- 布局系统 - 即字面意思,用来负责界面的各个元素的位置。
AutoLayout和Autoresizing Mask的区别
Autoresizing Mask是我们的老朋友了…如果你以前一直是代码写UI的话,你肯定写过UIViewAutoresizingFlexib- AutoLayout可以指定任意两个view的相对位置,而不需要像Autoresizing Mask那样需要两个view在直系的view hierarchy中。
- AutoLayout不必须指定相等关系的约束,它可以指定非相等约束(大于或者小于等);而Autoresizing Mask所能做的布局只能是相等条件的。
- AutoLayout可以指定约束的优先级,计算frame时将优先按照满足优先级高的条件进行计算。
Autoresizing Mask是AutoLayout的子集,任何可以用Autoresizing Mask完成的工作都可以用AutoLayout完成。AutoLayout还具备一些Autoresizing Mask不具备的优良特性,以帮助我们更方便地构建界面。
AutoLayout基本使用方法
Interface Builder
这部分网上大量的教程,都是说的这个
手动使用API添加约束
创建
iOS6中新加入了一个类:NSLayoutConstraint,一个形如这样的约束- item1.attribute = multiplier ? item2.attribute + constant
1 | [NSLayoutConstraint constraintWithItem:button |
2 | attribute:NSLayoutAttributeBottom |
3 | relatedBy:NSLayoutRelationEqua |
4 | toItem:superview |
5 | attribute:NSLayoutAttributeBottom |
6 | multiplier:1.0 |
7 | constant:-padding] |
添加
在创建约束之后,需要将其添加到作用的view上。UIView(当然NSView也一样)加入了一个新的实例方法:- -(void)addConstraint:(NSLayoutConstraint *)constraint;
- 对于两个同层级view之间的约束关系,添加到他们的父view上
- 对于两个不同层级view之间的约束关系,添加到他们最近的共同父view上
- 对于有层次关系的两个view之间的约束关系,添加到层次较高的父view上
刷新
可以通过-setNeedsUpdateConstraintVisual Format Language 可视格式语言
UIKit团队这次相当有爱,估计他们自己也觉得新加约束的API名字太长了,因此他们发明了一种新的方式来描述约束条件,十分有趣。这种语言是对视觉描述的一种抽象,大概过程看起来是这样的: accept按钮在cancel按钮右侧默认间距处最后使用VFL(Visual Format Language)描述变成这样:
1 | [NSLayoutConstraint constraintsWithVisualFor "[cancelButton]-[acceptButton]\" |
2 | options:0 |
3 | metrics:nil |
4 | views:viewsDictionary]; |
1 | UIButton *cancelButton = ... |
2 | UIButton *acceptButton = ... |
3 | viewsDictionary = NSDictionaryOfVariableBi |
{ acceptButton = ""; cancelButton = ""; }
当然,不嫌累的话自己手写也未尝不可。现在字典啊数组啊写法相对简化了很多了,因此也不复杂。关于Objective-C的新语法,可以参考我之前的一篇WWDC 2012笔记:WWDC 2012 Session笔记——405 Modern Objective-C。 在view名字后面添加括号以及连接处的数字可以赋予表达式更多意义,以下进行一些举例:
- [cancelButton(72)]-12-[acceptButton(50)]
- 取消按钮宽72point,accept按钮宽50point,它们之间间距12point
- [wideView(>=60@700)]
- wideView宽度大于等于60point,该约束条件优先级为700(优先级最大值为1000,优先级越高的约束越先被满足)
- V:[redBox][yellowBox(==redBox)]
- 竖直布局,先是一个redBox,其下方紧接一个宽度等于redBox宽度的yellowBox
- H:|-[Find]-[FindNext]-[FindField(>=20)]-|
- 水平布局,Find距离父view左边缘默认间隔宽度,之后是FindNext距离Find间隔默认宽度;再之后是宽度不小于20的FindField,它和FindNext以及父view右边缘的间距都是默认宽度。(竖线'|‘ 表示superview的边缘)
容易出现的错误
因为涉及约束问题,因此约束模型下的所有可能出现的问题这里都会出现,具体来说包括两种:- Ambiguous Layout 布局不能确定
- Unsatisfiable Constraints 无法满足约束
- po [[UIWindow keyWindow] _autolayoutTrace]
- [view constraintsAffectingLayo
utForOrientation/Axis: NSLayoutConstraintOrient ationHorizontal/Vertical] - [view hasAmbiguousLayout]
- [view exerciseAmbiguityInLayou
t]
- [view exerciseAmbiguityInLayou
布局动画
动画是UI体验的重要部分,更改布局以后的动画也非常关键。说到动画,Core Animation又立功了..自从CA出现以后,所有的动画效果都非常cheap,在auto layout中情况也和collection view里一样,很简单(可以参考WWDC 2012 Session笔记——219 Advanced Collection Views and Building Custom Layouts),只需要把layoutIfNeeded放到animation block中即可~ 1 | [UIView animateWithDuration:0.5 animations:^{ |
2 | [view layoutIfNeeded]; |
3 | }]; |
部分代码
纯净代码UI正常布局后,添加autolayout就可以了,调整相当方便
这是一段水平居中,垂直并列的4个按钮 布局代码
setTranslatesAutoresizin gMaskIntoConstraints 是为no,开启AutoLayou.
纯净代码UI正常布局后,增加一个函数,进行自动布局
水平居中布局:NSLayoutAttributeCenterX
垂直居中布局:NSLayoutAttributeCenterY
以及后面的布局切换动画。
-----------------------------------------
网上相关文章:
-----------------------------------------
1、AutoLayout(自动布局)入门 推荐
2、Autolayout及VFL经验分享 此文包含有一个demo(快速访问下载) 推荐
不是朋友在发愁手动些这些类似脚本的字符:
现在推荐一个开源库给大家
git@OSC: http://git.oschina.net/TelenLiu/Lyt