AutoLayout
首先,使用AutoLayout就要忘了Frame的概念。
因为AutoLayout是相对布局,所以你通常不应该直接设置宽度和高度这种固定不变的值,除非你很确定视图的宽度和高度需要保持不变。
(1)如何正确的设置宽度或高度?
1> 如果宽度和高度布局可以改变,使用固有尺寸(intrinsic Content Size) 设置约束(size to fit size)
2>如果宽度和高度布局不可以改变,设置约束的关系为>=
3>调整压缩优先级和内容抗压缩优先级
(2)约束是根据视图层级自上而下更新的,也就是子视图到父视图。规则:
1>两个同层级视图的约束,添加到他们共同的父视图上
2>两个不同层级视图的约束,添加到他们最近的共同的父视图上
3>两个有层级关系的视图的约束,添加到层次级较高的视图上
可以通过-layoutIfNeeded和-setNeedsUpdateConstraints两个方法来刷新约束的改变,使UIView重新布局。layoutIfNeeded是调整布局,也就是view的位置,一般是对subviews作用。setNeedsDisplay涉及到redraw,也就是重绘,一般都是对receiver作用。
layoutIfNeeded
使用此方法强制立即进行layout,从当前view开始,此方法会遍历整个view层次(包括superviews)请求layout。因此,调用此方法会强制整个view层次布局。更新约束后立刻生效时使用。
setNeedsUpdateConstraints
当一个自定义view的某个属性发生改变,并且可能影响到constraint时,需要调用此方法去标记constraints需要在未来的某个点更新,系统然后调用updateConstraints.
NSLayoutConstraint方法一:
[NSLayoutConstraint constraintWithItem:(id)item attribute:(NSLayoutAttribute)attribute relatedBy:(NSLayoutRelation)relation toItem:(id)otherItem attribute:(NSLayoutAttribute)otherAttribute multiplier:(CGFloat)multiplier constant:(CGFloat)constant] 参数说明: 第一个参数:指定约束左边的视图view1 第二个参数:指定view1的属性attr1,具体属性见文末。 第三个参数:指定左右两边的视图的关系relation,具体关系见文末。 第四个参数:指定约束右边的视图view2 第五个参数:指定view2的属性attr2,具体属性见文末。 第六个参数:指定一个与view2属性相乘的乘数multiplier 第七个参数:指定一个与view2属性相加的浮点数constant attribut可以是上下左右宽高等等。 注意: 1.如果你想设置的约束里不需要第二个view,要将第四个参数设为nil,第五个参数设为NSLayoutAttributeNotAnAttribute 属性和关系的值: typedef NS_ENUM(NSInteger, NSLayoutRelation) { NSLayoutRelationLessThanOrEqual = -1, //小于等于 NSLayoutRelationEqual = 0, //等于 NSLayoutRelationGreaterThanOrEqual = 1, //大于等于 }; typedef NS_ENUM(NSInteger, NSLayoutAttribute) { NSLayoutAttributeLeft = 1, //左侧 NSLayoutAttributeRight, //右侧 NSLayoutAttributeTop, //上方 NSLayoutAttributeBottom, //下方 NSLayoutAttributeLeading, //首部 NSLayoutAttributeTrailing, //尾部 NSLayoutAttributeWidth, //宽度 NSLayoutAttributeHeight, //高度 NSLayoutAttributeCenterX, //X轴中心 NSLayoutAttributeCenterY, //Y轴中心 NSLayoutAttributeBaseline, //文本底标 NSLayoutAttributeNotAnAttribute = 0 //没有属性 };
实现如下效果的布局:红色、绿色、黄色View距离左右上下间距都是20,红色、绿色宽高相等,黄色高度红色,绿色相等。
1. 关掉autoresizing的影响
_view1.translatesAutoresizingMaskIntoConstraints = NO;
_view2.translatesAutoresizingMaskIntoConstraints = NO;
_view3.translatesAutoresizingMaskIntoConstraints = NO;
2. 设置添加约束
// view1 和 view2 的水平约束 attribute属性 relate把什么...联系起来 multiplier乘数 Layout排版,布局 Relation关系 equal相同的 NSLayoutConstraint *view1Left = [NSLayoutConstraint constraintWithItem:_view1 attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeLeading multiplier:1 constant:20]; NSLayoutConstraint *view1Width = [NSLayoutConstraint constraintWithItem:_view1 attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:_view2 attribute:NSLayoutAttributeWidth multiplier:1 constant:0]; NSLayoutConstraint *view1Right = [NSLayoutConstraint constraintWithItem:_view1 attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:_view2 attribute:NSLayoutAttributeLeading multiplier:1 constant:-20]; NSLayoutConstraint *view2Right = [NSLayoutConstraint constraintWithItem:_view2 attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeTrailing multiplier:1 constant:-20]; // view1 和 view3 的垂直约束 NSLayoutConstraint *view1Top = [NSLayoutConstraint constraintWithItem:_view1 attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeTop multiplier:1 constant:20]; NSLayoutConstraint *view1Height = [NSLayoutConstraint constraintWithItem:_view1 attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:_view3 attribute:NSLayoutAttributeHeight multiplier:1 constant:0]; NSLayoutConstraint *view1Bottom = [NSLayoutConstraint constraintWithItem:_view1 attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:_view3 attribute:NSLayoutAttributeTop multiplier:1 constant:-20]; NSLayoutConstraint *view3Bottom = [NSLayoutConstraint constraintWithItem:_view3 attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeBottom multiplier:1 constant:-20]; // view2 的垂直约束 NSLayoutConstraint *view1CenterY = [NSLayoutConstraint constraintWithItem:_view1 attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:_view2 attribute:NSLayoutAttributeCenterY multiplier:1 constant:0]; NSLayoutConstraint *view2Height = [NSLayoutConstraint constraintWithItem:_view1 attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:_view2 attribute:NSLayoutAttributeHeight multiplier:1 constant:0]; // view3 的水平约束 NSLayoutConstraint *view3Left = [NSLayoutConstraint constraintWithItem:_view3 attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeLeading multiplier:1 constant:20]; NSLayoutConstraint *view3Right = [NSLayoutConstraint constraintWithItem:_view3 attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeTrailing multiplier:1 constant:-20]; // 添加约束 [self.view addConstraints:@[view1Left,view1Width,view1Right,view2Right,view1Top,view1Height,view1Bottom,view3Bottom,view1CenterY,view2Height,view3Left,view3Right]];
NSLayoutConstraint方法二:Visual Format Language(可视格式语言)
NSDictionary *views = NSDictionaryOfVariableBindings(self.view, _view1, _view2, _view3); [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-20-[_view1(_view2)]-20-[_view2]-20-|" options:NSLayoutFormatAlignAllTop|NSLayoutFormatAlignAllBottom metrics:0 views:views]]; [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-20-[_view3]-20-|" options:0 metrics:0 views:views]]; [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-20-[_view1(_view3)]-20-[_view3]-20-|" options:0 metrics:0 views:views]];
VFL语法:
1. H/V表示布局方向。H表示水平方向(Horizontal),V表示垂直方向(Vertical),方向后要紧跟一个: 不能有空格!
2. | 表示父视图,通常出现在语句的首尾
3. -有两个用途,单独一个表示标准距离。这个值通常是8;两个中间夹着数值,表示使用中间的数值代替标准距离。如-50-,就是使用50来代替标准距离
4. []表示对象,中间需要填上对象名,对象名必须是我们传入的views字典中的键。对象名后可以跟小括号(),小括号中是对对象的尺寸和优先级的约束。水平布局中尺寸是宽度,垂直布局中尺寸是高度。
@"|-50-[_view1(80@100)]-[_view2(90@200)]-50-|"
//这条语句的含义是:“左右边距都为50,中间有两个按钮,相隔缺省宽度,_view1宽度为80,约束优先级为100;_view2宽度为90,约束优先级为 200”。实际运行后,发现_view2宽度为90,而_view1的宽度为自适应宽度,并不是80像素;这是因为_view2的约束优先级 200大于_view1的约束优先级,所以优先生效。
优先级:系统内置了4个优先级
enum{ UILayoutPriorityRequired = 1000 UILayoutPriorityDefaultHigh = 750, UILayoutPriorityDefaultLow = 250, UILayoutPriorityFittingSizeLevel = 50, }; typedef float UILayoutPriority;
1. 优先级的取值范围0--1000,数值越大,优先被满足。
2. 每个约束的默认优先级就是UILayoutPriorityRequired,这意味着你给出的所有约束都必须得到满足,一旦约束间发生冲突,你的应用就会Crash.这也是在使用AutoLayout时经常会犯的错误:没有给约束设置优先级。
3. 在约束值后加@符号就可以设置优先级。
NSLayoutConstraint方法三:引用第三方库
1. 下载Masonry 并添加到项目 包含头文件#import "Masonry.h"
2. 代码实现
[_view1 mas_makeConstraints:^(MASConstraintMaker *make) { make.top.equalTo(self.view).with.offset(20); make.leading.equalTo(self.view.mas_leading).with.offset(20); make.leading.equalTo(_view3); make.bottom.equalTo(_view3.mas_top).with.offset(-20); make.trailing.equalTo(_view2.mas_leading).with.offset(-20); make.size.equalTo(_view2); make.height.equalTo(_view3); }]; [_view2 mas_makeConstraints:^(MASConstraintMaker *make) { make.centerY.equalTo(_view1); make.trailing.equalTo(self.view.mas_trailing).with.offset(-20); make.trailing.equalTo(_view3); }]; [_view3 mas_makeConstraints:^(MASConstraintMaker *make) { make.bottom.equalTo(self.view.mas_bottom).with.offset(-20); }];
原文:http://www.cnblogs.com/10-19-92/p/4888148.html