Width:对视图宽度的约束
Height:对视图高度的约束
Horizontal Spacing:对视图间水平距离的约束
Vertical Spacing:对视图间垂直距离的约束
Leading Space to Superview:与父视图左边界的约束
Trailing Space to Superview:与父视图右边界的约束
Top Space to Superview:与父视图上边界的约束
Bottom Space to Superview:与父视图下边界的约束
Widths Equally:视图等宽约束
Heights Equally:视图等高约束
Auto Layout 中约束对应的类为 NSLayoutConstraint,一个 NSLayoutConstraint 实例代表一条约束。 (在iOS6之后,引入了autolayout这个概念,相应的也增加了NSLayoutConstraint这个对象,这个对象就是专门用来进行约束布局的设置对象。通过这个对象,我们可以设置类似视图对象之间的间距,约束的宽高,比例等属性。创建NSLayoutConstraint对象的方法有两种:)
NSLayoutConstraint有两个方法,我们主要介绍 constraintWithItem:也是最常用的。
+ (instancetype)constraintWithItem:(id)view1 attribute:(NSLayoutAttribute)attr1 relatedBy:(NSLayoutRelation)relation toItem:(nullable id)view2 attribute:(NSLayoutAttribute)attr2 multiplier:(CGFloat)multiplier constant:(CGFloat)c API_AVAILABLE(macos(10.7), ios(6.0), tvos(9.0));
意思是:(描述的是一个view与另外一个view的位置和大小约束关系。)
view1:要添加约束的视图对象。
view2:与之对应添加约束的视图对象,例如,如过我要设置view1的上边距离父视图的上边一定间距,这个view2就是view1的父视图。
attribute(属性):有上、下、左、右、宽、高等。
relation(关系):有(<=,==,>=)小于等于、等于、大于等于。(注意:小于等于或大于等于优先会使用等于关系,如果等于不能满足,才会使用小于或大于。例如设置一个大于等于100 的关系,默认会是 100,当视图被拉伸时,100 无法被满足,尺寸才会变得更大。)
multiplier(比例):约束的比例,比如view1的宽是view2的宽的两倍,这个multiplie就是2.
AutoLayout 的核心计算公式:
view1.attribute1 = view2.attribute2 * multiplier + constant value
item1 =(>=,<=) multiplier * item2 + constant。
举个简单的例子来说我们想设置第一个视图的宽度是第二个视图宽度的2倍,我们可以这样写:
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:view2 attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:view1 attribute:NSLayoutAttributeWidth multiplier:2 constant:0]];
在这个方程式中,attribute1 和 attribute2 是自动布局可以调整时解决这些制约因素的变量。当你创建约束定义其他值。例如,如果您定义两个按钮的相对位置,第二个按钮的起始位置距离第一个按钮结束位置后8像素点。这种关系为线性方程如下所示:
button2.leading = 1.0 × button1.trailing + 8.0
例如一: 假如我们设计一个简单的页面。一个子view在父view中,其中子view的上下左右边缘都离父view的边缘40个像素。如下:
//设置背景颜色
self.view.backgroundColor = [UIColor redColor];
//创建子view
UIView *subView = [[UIView alloc]init];
//设置子view背景颜色
subView.backgroundColor = [UIColor blackColor];
//将子view添加到父视图上
[self.view addSubview:subView];
//使用Auto Layout约束,禁止将Autoresizing Mask转换为约束
[subView setTranslatesAutoresizingMaskIntoConstraints:NO];
//layout 子view
//子view的上边缘离父view的上边缘40个像素
NSLayoutConstraint *contraint1 = [NSLayoutConstraint constraintWithItem:subView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeTop multiplier:1.0 constant:40.0];
//子view的左边缘离父view的左边缘40个像素
NSLayoutConstraint *contraint2 = [NSLayoutConstraint constraintWithItem:subView attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeLeft multiplier:1.0 constant:40.0];
//子view的下边缘离父view的下边缘40个像素
NSLayoutConstraint *contraint3 = [NSLayoutConstraint constraintWithItem:subView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeBottom multiplier:1.0 constant:-40.0];
//子view的右边缘离父view的右边缘40个像素
NSLayoutConstraint *contraint4 = [NSLayoutConstraint constraintWithItem:subView attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeRight multiplier:1.0 constant:-40.0];
//把约束添加到父视图上
NSArray *array = [NSArray arrayWithObjects:contraint1,contraint2,contraint3,contraint4, nil];
[self.view addConstraints:array];
注意事项:
添加约束前确定已经把需要布局的子view添加到父view上了
(添加约束之前,一定要保证相关控件都已经在各自的父控件上。用上面的例子就是 [self.view
addSubview:purpleView]; 一定要放在添加 left 约束之前,否则程序会 crash-崩溃,因为要确保
purpleView 要已经在 self.view 上了。建议先写 [self.view addSubview:purpleView];
之后,再专心写约束。)
一定要禁止将Autoresizing Mask转换为约束
view.translatesAutoresizingMaskIntoConstraints = NO; (要先禁止
autoresizing 功能,防止 AutoresizingMask 转换成 Constraints,避免造成冲突,需要设置 view
的下面属性为 NO:)
要把子view的约束加在父view上
因为iOS中原点在左上角所以使用offset时注意right和bottom用负数
不用再给 view 设置 frame
例如二: 子view在父view的中间,且子view长300,高200。
//设置背景颜色
[self.view setBackgroundColor:[UIColor redColor]];
//创建子view
UIView *subView = [[UIView alloc] init];
//设置子view背景颜色
[subView setBackgroundColor:[UIColor blackColor]];
//将子view添加到父视图上
[self.view addSubview:subView];
//使用Auto Layout约束,禁止将Autoresizing Mask转换为约束
[subView setTranslatesAutoresizingMaskIntoConstraints:NO];
//layout 子view
//子view的中心横坐标等于父view的中心横坐标 (水平居中)
NSLayoutConstraint *constrant1 = [NSLayoutConstraint constraintWithItem:subView attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterX multiplier:1.0 constant:0.0];
//子view的中心纵坐标等于父view的中心纵坐标(垂直居中)
NSLayoutConstraint *constrant2 = [NSLayoutConstraint constraintWithItem:subView attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterY multiplier:1.0 constant:0.0];
//子view的宽度为300 这里直接设置自身宽为300
NSLayoutConstraint *constrant3 = [NSLayoutConstraint constraintWithItem:subView attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationGreaterThanOrEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:300.0];
//设置自身宽,宽可以参照其他控件设置,比如是self.view宽的一半,则应该这样写
//参照其他控件设置位置
NSLayoutConstraint *contraint = [NSLayoutConstraint constraintWithItem:libraryView attribute:NSLayoutAttributeToprelatedBy:NSLayoutRelationEqual toItem:labelLibrary attribute:NSLayoutAttributeBottom multiplier:1.0 constant:20.0];
//距离父视图底部40
NSLayoutConstraint *contraint = [NSLayoutConstraint constraintWithItem:btn attribute:NSLayoutAttributeBottomrelatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeBottom multiplier:1.0 constant:-40.0];
//居中显示
NSLayoutConstraint *contraint = [NSLayoutConstraint constraintWithItem:clickLabel attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:bgView attribute:NSLayoutAttributeCenterY multiplier:1.0 constant:0.0];
NSLayoutConstraint *contraint = [NSLayoutConstraint constraintWithItem:clickLabel attribute:NSLayoutAttributeCenterXrelatedBy:NSLayoutRelationEqual toItem:bgView attribute:NSLayoutAttributeCenterX multiplier:1.0 constant:0.0];
//子view的高度为200
NSLayoutConstraint *constrant4 = [NSLayoutConstraint constraintWithItem:subView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationGreaterThanOrEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:200.0];
//把约束添加到父视图上
NSArray *array = [NSArray arrayWithObjects:contraint1,contraint2,contraint3,contraint4, nil];
[self.view addConstraints:array];
//可以直接用addConstraints
[self.view addConstraints:@[[NSLayoutConstraint constraintWithItem:subView attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterX multiplier:1.0 constant:0.0], [NSLayoutConstraint constraintWithItem:subView attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterY multiplier:1.0 constant:0.0], [NSLayoutConstraint constraintWithItem:subView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationGreaterThanOrEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:200.0], [NSLayoutConstraint constraintWithItem:subView attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationGreaterThanOrEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:300.0]]];
注意事项:
在创建约束了之后,需要将其添加到作用的控件上才能生效,注意在添加约束的时候目标控件需要遵循以下规则(这里控件就用 view 表示):
可以看出,widthConstraint 和 Constraint 属于第(4)种,leftConstraint 和 rightConstraint 属于第(3)种。
例如四:
topView在父视图的左边间距10,下边间距-10,宽度为100,高度为20的实现代码
UIView *topView = [[UIView alloc] init];
topView.backgroundColor = [UIColor redColor];
[self.view addSubview:topView];
topView.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addConstraints:@[[NSLayoutConstraint constraintWithItem:topView attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeLeft multiplier:1.0 constant:10], [NSLayoutConstraint constraintWithItem:topView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeBottom multiplier:1.0 constant:-10], [NSLayoutConstraint constraintWithItem:topView attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:100],[NSLayoutConstraint constraintWithItem:topView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:20]]];
这么多方法中,目前使用比较多的是 layoutIfNeeded 。因为在Auto Layout 实现动画的时候,layoutIfNeeded 方法可以立刻生成新的frame特性是一大利器。