AutoLayout使用代码写约束
一、约束是什么?
约束是视图与视图之间一些属性关系。
我们先来了解一下下面的内容:
视图属性:视图属性(attribute)有left
, right
, top
, bottom
, leading
, trailing
, width
, height
, centerX
, centerY
和 baseline
。(注:iOS8加上了Margin
,所以实际上从iOS8开始不止这些)
约束属性:每一个约束(Constraint)拥有的属性(Property)有:
- Constant value: 偏移量
- Relation: 属性之间的关系,和关系表达式对应,例如>(大于),=(等于),>=(大于等于)
- Priority level: 优先级,优先级越高,越会满足此约束。
一个普通约束表达式: view1.attribute = view2.attribute + ConstantValue
例子:当你定义一个button的位置时,你可能会有这么一个要求:”按钮的左边距离父视图的左边20像素”。其实这句话用约束表达就是button.left = (superView.left + 20)
。
二、VFL(Visual Format Language)
1、语法
下面这是一些常用的VFL语法示例,如果想要知道更详细的语法规则,请查看Auto Layout Guide
2、VFL使用
我们现在需要做这么一个UI需求:页面中有两个元素一张图片和一个文本。图片距左右两边和顶部10像素,而距底部100像素;文本距图片30像素。这个用代码如何实现?请看下面代码:
|
|
如下是运行的效果图:
到这里,我们已经使用VFL实现了需求。
假如有一天,我们的产品经理觉得这个效果不好看,需要改一改,然后UI设计师重新出了一套效果图。上面的页面已经修改成:图片距左右两边和顶部10像素,而图片宽与高比例为5:7;描述文本处于水平居中位置,并且处于图片的下方与屏幕上方居中位置。
此时,我们用代码如何实现?
查看VFL语法,明显图片宽与高比例为5:7这个需求没有直接对应的语法,实现起来有点复杂。这时,我们可以使用苹果为我们封装的另外一个创建约束的方法constraintWithItem:attribute:relatedBy:toItem:attribute:multiplier:constant:
,就可以轻易实现我们的需求。如下,就是实现代码:
|
|
运行效果如下:
constraintWithItem:attribute:relatedBy:toItem:attribute:multiplier:constant:
方法主要是为了创建视图约束属性之间的关系,而这个方法的精髓主要是这么一个表达式:view1.attribute = view2.attribute * multiplier + constant。这里与我们前面讲过的表达式类似,只是多了一个multiplier的系数。
三、Masnory写约束
Masonry是一个轻量级的布局框架,拥有自己的描述语法,采用更优雅的链式语法封装自动布局,简洁明了 并具有高可读性。
上面的需求,我使用Masnory实现起来,代码简洁了很多,而且基本上不怎么需要学就能通过Masnory实现上面的需求,代码如下:
|
|
效果如下:
示例代码已经放到github上了,github代码示例
四、使用AutoLayout时,如何添加动画?
使用VFL时,动画改变尺寸或位置时,很简单只需要将对应的约束保存成全局变量,然后改变约束当中的属性就行了。
使用Autolayout动画改变尺寸、位置的官方模板如下:
[containerView layoutIfNeeded]; // Ensures that all pending layout operations have been completed
[UIView animateWithDuration:1.0 animations:^{
// Make all constraint changes here
[containerView layoutIfNeeded]; // Forces the layout of the subtree animation block and then captures all of the frame changes
}];
那如果使用的是Masnory框架,怎么添加动画?
我这里有个Demo,请看代码:
- (void)viewDidLoad {
[super viewDidLoad];
//创建displayView
UIView *displayView = [[UIView alloc] init];
displayView.backgroundColor = [UIColor purpleColor];
[self.view addSubview:displayView];
self.displayView = displayView;
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button setTitle:@"点击" forState:UIControlStateNormal];
[button setTitleColor:[UIColor darkGrayColor] forState:UIControlStateHighlighted];
[button setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];
[button addTarget:self action:@selector(buttonAction:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:button];
//添加约束
[displayView mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.view.mas_top).offset(100);
make.size.mas_equalTo(CGSizeMake(50, 50));
make.centerX.equalTo(self.view.mas_centerX);
}];
[button mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerX.equalTo(self.view.mas_centerX);
make.size.mas_equalTo(CGSizeMake(200, 50));
make.bottom.mas_equalTo(self.view.mas_bottom).offset(-50);
}];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)buttonAction:(UIButton *)butt on{
//动 画改变
[self.view layoutIfNeeded];
[UIView animateWithDuration:1.0 animations:^{
[self.displayView mas_updateConstraints:^(MASConstraintMaker *make) {
make.size.mas_equalTo(CGSizeMake(300, 300));
}];
[self.view layoutIfNeeded];
}];
}
示例代码已经放到github上了,github代码示例
五、什么时候使用代码写约束?
使用Xib写约束,可以很直观、快捷的搭建界面,让我们的开发速度提升很快。但,Xib开发有时候不是很灵活,这个时候我们就得考虑使用代码来实现约束。
以下几种情况,我觉得使用代码写约束比较适合:
- 运行时改变视图尺寸、位置的时候,应该使用代码写约束
- 封装一个控件时,使其能够有足够的灵活性,应该使用代码写约束
- 添加动画的时候,使用代码写约束。
- 一些复杂的UI,使用IB很难实现的场景,使用代码写约束
六、总结
这篇文章主要讲了下面一些东西
- 约束是什么
- VFL相关语法
- VFL的使用
- Masnory框架的使用
- 使用Autolayout时,添加动画
- 哪些场景下使用代码来写约束