可能有些人看到NSLayoutConstraint有点陌生,因为它并不受开发人员的欢迎,不怎么好用但是还有有了解的必要的;其实它是实现自动布局方式之一,因为我们每个APP都需要去适配,有人使用第三方Masonry,有人在Xib或者storyBoard中使用AutoLayout或者是Size Class进行布局;今天我们就认识一下NSLayoutConstraint,顺便给大家介绍好用的工具!
需要把控件的属性设置为 setTranslatesAutoresizingMaskIntoConstraints:NO,为了不让Contraint和view本身的autoresize属性发生冲突;如果你没有设置该属性,你的布局不起作用或者会报错。
主要的两个方法:
/*
format:V:|-(>=XXX) :表示垂直方向上相对于SuperView大于、等于、小于某个距离 若是要定义水平方向,则将V:改成H:即可 在接着后面-[]中括号里面对当前的View/控件 的高度/宽度进行设定;
opts:options:字典类型的值;这里的值一般在系统定义的一个enum里面选取
metrics:metrics:nil;一般为nil ,参数类型为NSDictionary,从外部传入 //衡量标准
views:views:就是上面所加入到NSDictionary中的绑定的View
### 使用规则:
|: 表示父视图
-:表示距离
V: :表示垂直
H: :表示水平
>= :表示视图间距、宽度和高度必须大于或等于某个值
<= :表示视图间距、宽度和高度必须小宇或等于某个值
== :表示视图间距、宽度或者高度必须等于某个值
@ :>=、<=、== 限制 最大为 1000
*/
+ (NSArray<__kindof NSLayoutConstraint *> *)constraintsWithVisualFormat:(NSString *)format options:(NSLayoutFormatOptions)opts metrics:(nullable NSDictionary<NSString *,id> *)metrics views:(NSDictionary<NSString *, id> *)views;
/*
view1:指定约束左边的视图view1
attr1:指定view1的属性attr1,具体属性见文末。
relation:指定左右两边的视图的关系relation,具体关系见文末。
view2:指定约束右边的视图view2
attr2:指定view2的属性attr2,具体属性见文末。
multiplier:指定一个与view2属性相乘的乘数multiplier
c:指定一个与view2属性相加的浮点数constant
这个函数的对照公式为: view1.attr1 <relation> view2.attr2 * multiplier + constant
*/
/*
NSLayoutAttribute:
NSLayoutAttributeLeft = 1, // 左侧
NSLayoutAttributeRight, // 右侧
NSLayoutAttributeTop, // 顶部
NSLayoutAttributeBottom, // 底部
NSLayoutAttributeLeading, // 首部
NSLayoutAttributeTrailing, // 尾部
NSLayoutAttributeWidth, // 宽度
NSLayoutAttributeHeight, // 高度
NSLayoutAttributeCenterX, // X轴中心
NSLayoutAttributeCenterY, //
NSLayoutAttributeBaseline,
NSLayoutAttributeNotAnAttribute = 0
*/
+(instancetype)constraintWithItem:(id)view1 attribute:(NSLayoutAttribute)attr1 relatedBy:(NSLayoutRelation)relation toItem:(nullable id)view2 attribute:(NSLayoutAttribute)attr2 multiplier:(CGFloat)multiplier constant:(CGFloat)c;
实际应用(使用工具就可以生成):
// align imageview from the left and right
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-0-[imageview]-0-|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(imageview)]];
// align imageview from the top and bottom
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-0-[imageview]-0-|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(imageview)]];
// center imageview horizontally in self.view
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:imageview attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterX multiplier:1.0 constant:0.0]];
// center imageview vertically in self.view
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:imageview attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterY multiplier:1.0 constant:0.0]];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:imageview attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationLessThanOrEqual toItem:self.view attribute:NSLayoutAttributeWidth multiplier:0.5 constant:0.0]];
Auto Layout 更新约束的几个方法
- setNeedsLayout:告知页面需要更新,但是不会立刻开始更新。执行后会立刻调用layoutSubviews。
- layoutIfNeeded:告知页面布局立刻更新。所以一般都会和setNeedsLayout一起使用。如果希望立刻生成新的frame需要调用此方法,利用这点一般布局动画可以在更新布局后直接使用这个方法让动画生效。
- layoutSubviews:系统重写布局。
- setNeedsUpdateConstraints:告知需要更新约束,但是不会立刻开始。
- updateConstraintsIfNeeded:告知立刻更新约束。
- updateConstraints:系统更新约束。