Autolayout经验分享
前言
首先要用Autolayout约束视图,你可以抛弃坐标系了。但并不意味着会更加方便.虽然AutoLayout可以适配不同的屏幕但是我觉得也不是很方便,有时候为了约束一个视图甚至要DEBUG很长时间(除非你很熟悉了该怎么用代码写),代码写也不下数七八行,仅仅只是一个视图而已,如果多个视图都需要约束,代码量可想而知。废话不多说开始吧
为了简化约束使用,本人自己封装了一套约束助手,可以大大简化约束的添加和使用(点击查看)
Autolayout的3个核心概念
1.参照
即你使用哪个视图作为参照来确定你想要的效果
2.约束
这个就不用多说了
3.核心公式
obj1.property1 =(obj2.property2 * multiplier)+ constant value
1.>先说明代码约束视图
对一个对象使用自动布局分为以下步骤
1.拿到视图对象(废话,不拿到对象约束个毛线)
2.设置视图 `view.translatesAutoresizingMaskIntoConstraints=NO`
3.将视图添加到父视图,一个视图没有父视图用autolayout绝对会崩,因为父视图都木有鬼知道这个视图怎么相对其他视图确定位置
这三个都是准备步骤,木有技术含量。
4.用代码写约束(这最重要的)
5.添加你用代码写的约束到作用视图上去,使用UIView的方法[self.view addConstraint:](单个约束)
[self.view addConstraints:](多个约束)(这里的作用视图待会给你解释清楚)
作用视图说明
在添加时要注意目标view需要遵循以下规则
1.对于两个同层级view之间的约束关系,添加到它们的父view上
2.对于两个不同层级view之间的约束关系,添加到他们最近的共同父view上
3.对于有层次关系的两个view之间的约束关系,添加到层次较高的父view上
(这里引用李明杰老师的)
2.>代码说明
对上面的第4点说明,我们该怎样用代码获得约束呢?
首先“约束”也是对象
用来表征该对象的类是NSLayoutConstraint
这下你应该明白了,我们应该用NSLayoutConstraint来创建并得到约束
并且我们经常只用以下两种方法,其他方法你可以先不考虑。
方法1:
+ (NSArray *)constraintsWithVisualFormat:(NSString *)format options:(NSLayoutFormatOptions)opts metrics:(NSDictionary *)metrics views:(NSDictionary *)views;
看返回值就知道这个数组里面装着多个约束 添加到对应的view应该用view 的addConstraints:方法
format :VFL语句
opts :约束类型
metrics :VFL语句中用到的具体数值
views :VFL语句中用到的控件
方法2:
+(instancetype)constraintWithItem:(id)view1 attribute:(NSLayoutAttribute)attr1 relatedBy:(NSLayoutRelation)relation toItem:(id)view2 attribute:(NSLayoutAttribute)attr2 multiplier:(CGFloat)multiplier constant:(CGFloat)c;
view1 : 要约束的控件
attr1 : 约束的类型(做怎样的约束)
relation : 与参照控件之间的关系
view2 : 参照的控件
attr2 : 约束的类型(做怎样的约束)
multiplier : 乘数
c : 常量 (该常量可以更改)
这个方法是用来返回单个约束
不要看上面两个方法参数那么多就懵了,苹果设计API都是有依据的。其实理解还是比较自然的。
Tips:
要想用Autolayout正确约束视图,你必须自己想想你该怎样约束这个视图让其确定一个位置,如果你给出的代码约束不明确就会出问题。什么是不明确的代码约束呢?比如,我约束了一个视图的长度height和宽度width然后又约束了该视图的左边left距离父视图左边一定距离,显然这个时候符合该视图的位置有无数种因为无法确定竖直方向的位置 ,想要修正就要添加一个能再竖直方向上确定位置的约束,比如该视图的顶部距离父视图的顶部多少,或者该视图的底部距离父视图的底部多少.
总结:你必须给出能够明确该视图位置的约束,少一个都不行,但有些控件可以不用给出width和height约束.
例如UILabel,你只给出label的顶部,左边的约束就行了,因为label内部文本知道自己的宽和高是多少.UIButton,和UILabel一样.UIImageView,同样你可以只给出两个约束(顶部和左边 或者 右边和底部等等),因为imageView的内部你设置了image属性就等于告诉了imageView的宽和高,但是在StoryBoard和XIB中会有警告⚠️,你得设置占位图片来消除,不然你直接给出宽和高也行.
代码展示
这里有一个控制器视图为self.view
//按步骤开始准备工作
UIView *blueView=[[UIView alloc] init] ;
blueView.translatesAutoresizingMaskIntoConstraints=NO;
[self.view addSubview:blueView];
//开始写约束 (leftConstraint) "blueView"的 "左边" = "self.view"的"左边" 的 "1倍" +"20"
//知道下面这句代码里面7个参数分别是什么了吧
//这就是按照核心计算公式来写的
NSLayoutConstrsint *leftConstraint=[NSLayoutConstrsint constraintWithItem:blueView attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem: self.view attribute:NSLayoutAttributeLeft multiplier:1 constant:20];
NSLayoutConstrsint *rightConstraint=[NSLayoutConstrsint constraintWithItem:blueView attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem: self.view attribute:NSLayoutAttributeRight multiplier:1 constant:-20];
NSLayoutConstrsint *topConstraint=[NSLayoutConstrsint constraintWithItem:blueView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem: self.view attribute:NSLayoutAttributeTop multiplier:1 constant:20];
NSLayoutConstrsint *bottomConstraint=[NSLayoutConstrsint constraintWithItem:blueView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem: self.view attribute:NSLayoutAttributeBottom multiplier:1 constant:-20];
[self.view addConstraint:leftConstraint];
[self.view addConstraint:rightConstraint];
[self.view addConstraint:topConstraint];
[self.view addConstraint:bottomConstraint];
刚好8行代码
动画部分
在修改了约束之后,只要执行下面代码,就能做动画效果
[UIView animateWithDuration:1.0 animations:^{
[添加了约束的view layoutIfNeeded];
}];