- [干货Example代码](## 干货Example代码)
- [如何设置AutoLayout](## 如何设置AutoLayout)
- [如何正确添加AutoLayout](## 如何正确添加AutoLayout)
- [何时可以确定Frame](## 何时可以确定Frame)
- [动态更新AutoLayout](## 动态更新AutoLayout)
- [AutoLayout使用大坑提示](## AutoLayout使用大坑提示)
干货Example代码
1 | - (void)instituteSubviews { |
如何设置AutoLayout
一旦使用AutoLayout 的话与之对应的是所有View的Frame就无效了,需要通过指令设置
1 | [view setTranslatesAutoresizingMaskIntoConstraints:NO]; |
添加约束的方法有单条和多条两种,注意后边的“s”,单条约束添加的是NSLayoutConstraint,而多条约束添加的是以NSLayoutConstraint为元素的数组
1 | [view addConstraint:(NSLayoutConstraint *)constraint]; |
对应生成NSLayoutcontraint的方法也有两种,单条生成和生成一个数组,生成数组的方法称为VFL(Visual format language),类似颜文字的逗比方式
1 | /* Create constraints explicitly. Constraints are of the form "view1.attr1 = view2.attr2 * multiplier + constant" |
就像苹果源文件里注释的一样,单条生成的方法是要遵循一定公式的,公式是可以进行交换运算和乘除的。但是苹果的工作人员发现,这个坑爹的函数实在太长了,以至于最后一个参数的形参只用了一个c,所以才会有VFL
1 | //(NSArray<__kindof NSLayoutConstraint *> *) |
如何正确添加AutoLayout
添加autolayout必须遵循以下原则
- 最多只需要4条约束来确定一个控件的Frame的(originalX,originalY,Width,Height).即XY坐标和长宽
- iOS 7.0之前因为苹果的设计不严密,类似[imageView setImage]这种image自带宽高度的,如果在NSLayoutConstraint里不给定宽高就会报错。
- 7.0之后如果没有imageView设置宽高,就会去按照图片的宽高来,如果指定了,就会拉伸和缩放。
在确定了四项属性后,需要在正确的View添加上约束
- view添加必须正确,[view(父控件) addConstraint:[NSLayoutConstraint constraint(子控件)]]时view必须为父控件,才能控制子控件的布局。
- view可以为子控件, 但是仅能控制子控件本身的长宽高
- 因为控件添加逻辑的较为麻烦,苹果推荐使用[NSLayoutConstraint activateConstraints]和[NSLayoutConstraint deactivateConstraints]和active属性,会自动查找分辨自己的父控件和子控件。但是OS X10.10和iOS 8.0之后才可用
VFL中字符串的意义
H:|[view()]-gap-|
- H/V: 代表横向和竖向
- |: 代表侧边,横向时是左侧边和右侧边,纵向是上下
- []: 代表控件View,内部是views添加的控件字符串名字,注意下文大坑提示
- (): 代表控件的尺寸,可以直接用梳子,也可以用Metrics中key:value中key的字符串
- -: 代表标准间距,貌似是5左右,也可以”-gap-“代表固定间距,gap可以直接为数字,也可以是metric
- <=/>= : 任意间距和尺寸前可以用大于小于号描述,如”->=gap-“
何时可以确定Frame
虽然autolayout和控件的Frame互相冲突,但是并不是说Frame始终无法获取。以下是生命周期中可以获取到Frame的函数
- UIView: drawRect();
- UIViewController: ViewDidAppear();
动态更新AutoLayout
- 单条约束动态更新
1 | //.h |
- 多条约束动态更新
1 | //.h |
- 自定义View两套Contraints切换
1 | //在自定义的View中重载函数 |
以上动态更新都可以放在[UIView animateWithDuration:0.2 animations:^{}]中平滑过渡
AutoLayout使用大坑提示
ScrollView的大坑
- ScrollView 虽然是[self addConstraint]但是ScrollView不具有右侧边和下侧边,所以不可以在VFL中使用”H:|[view]|”以右侧或者下侧边做为约束的字符串,必须使用“H:|[view(ScreenWidth)]”这种有固定长度的
TableViewCell的大坑
- TalbleViewCell的Autolayout需要在ContentView中布局,虽然iOS7种[self addConstraint]可以编译通过,但是会在旧版本带来不可预知错误
VFL的大坑
- Metrics里不能有label.5x这样的 不能用小数点
- metrics是一个key:value均为字符串的字典,如100应当声明为 @”keyName”:@”100”
生命周期调用大坑
- -(void)viewWilllayoutsubviews; 这个函数通过重载也可以用来动态更新,但是7.0和以下需要手动去调用,因为7.0只在生成时调用一次,而8.0之后会每次界面出现都会自动调用
SearchController大坑
- searchController和autolayoutConstraint貌似不能一起用,因为SearchController搜索时会发生布局变化造成崩溃
- 也可能是我当时写的时候自己太挫了,哪里写的不对,这条待验证