Autolayout进阶之代码编写约束(一)
在我看来,Autolayout是开发神器,但是它也有局限之处。拿cell来举例,如果cell中的控件个数不确定,根据后台所给的数据来控制显示控件个数,那么Autolayout就不能简单的在xib上“拖”出来,而需要在代码中编写。这种情况在实际开发中是很常见的。我们再来看看原生代码的手写约束:
NSLayoutConstraint* leftConstraint = [NSLayoutConstraint constraintWithItem:logoImageView attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeLeading multiplier:1.0f constant:0.0f];
//logoImageView右侧与父视图右侧对齐
NSLayoutConstraint* rightConstraint = [NSLayoutConstraint constraintWithItem:logoImageView attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeTrailing multiplier:1.0f constant:0.0f];
//logoImageView顶部与父视图顶部对齐
NSLayoutConstraint* topConstraint = [NSLayoutConstraint constraintWithItem:logoImageView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeTop multiplier:1.0f constant:0.0f];
//logoImageView高度为父视图高度一半
NSLayoutConstraint* heightConstraint = [NSLayoutConstraint constraintWithItem:logoImageView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeHeight multiplier:0.5f constant:0.0f];
//iOS 6.0或者7.0调用addConstraints
//[self.view addConstraints:@[leftConstraint, rightConstraint, topConstraint, heightConstraint]];
是不是很难记?和frame相比,也变得更抽象,代码量也更多。谁会愿意摆放一个控件写那么多代码?幸运的是,现在我们有很多第三方框架来帮我们简化这些代码。
Masonry和SDAutolayout
目前网上流行AutoLayout框架主要是Masonry和SDAutolayout。前者是我目前项目中常用的框架,主要是用block回调,并且将复杂的约束讲话成MASConstraintMaker进行约束封装。后者是声称比Masonry更简单易用的约束框架,采用链式编程的思想对约束进行封装,并能实现cell高度自适应。下面我们来看看具体的使用方法。
Masonry框架
- Masonry是公认非常简洁优美的一款Autolayout框架
- gitHub地址:https://github.com/SnapKit/Masonry
- 推荐用cocoapods安装(如果不知道还是网上搜索下,开发必备)pod search Masonry
- 非常适合拿来练手
首先#import "Masonry.h"
导入头文件,然后就可以用代码进行约束编写:
//初始化一个view
UIView * redView = [[UIView alloc]init];
redView.backgroundColor = [UIColor redColor];
//然后将这个view添加到界面上
[self.view addSubview:redView];
//然后进行约束设置
[redView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(self.view).offset(100);
make.right.equalTo(self.view).offset(-200);
make.top.equalTo(self.view).offset(100);
make.height.mas_equalTo(100);
}];
先看这一段代码,首先创建了一个UIView,将背景色设成红色,然后进行约束设置。Masonry的命名都很直观,唯一要解释的可能就是这个make。我们可以理解成这个make就是redView本身,make.left.equalTo(self.view).offset(100);
就是设置redView
的左侧相对于self.view
偏移量为100。这种思想和在xib上拖线的思想是一致的。再来看看设置自己本身高度的约束make.height.mas_equalTo(100);
和上面一条唯一的区别就是mas_equalTo
。还有一点需要注意的是.offset
的值,如果前面是make.left(或者make.leading)和make.top,那么offset中设置的值为正数,如果是make.right(或者make.trailing)和make.bottom,那么offset中的值设成负数。
我们都知道,约束都有优先级。在Masonry语法中设置优先级也很简单,make.height.mas_equalTo(100).priority(500);
只要在后面添上.priority(优先级)就行了,如果不添加,默认优先级为1000。
再看另外一个例子:
//初始化一个view
UIView * redView = [[UIView alloc]init];
redView.backgroundColor = [UIColor redColor];
UIView * greenView = [[UIView alloc]init];
greenView.backgroundColor = [UIColor greenColor];
//然后将这个view添加到界面上
[self.view addSubview:redView];
[self.view addSubview:greenView];
//然后进行约束设置
[redView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(self.view).offset(100);
make.right.equalTo(greenView.mas_left).offset(-50);
make.top.equalTo(self.view).offset(100);
make.height.mas_equalTo(100).priority(500);
}];
[greenView mas_makeConstraints:^(MASConstraintMaker *make) {
make.right.equalTo(self.view).offset(-30);
make.top.equalTo(self.view).offset(100);
make.height.mas_equalTo(100);
make.width.mas_equalTo(100);
}];
这里要注意的是make.right.equalTo(greenView.mas_left).offset(-50);
这个写法,中间的括号是greenView.mas_left,应该也很好理解。
效果:
关于mas_makeConstraints
,mas_updateConstraints
和mas_remakeConstraints
的用法都是相同的,官方的API文档是这样描述的:
/**
* Creates a MASConstraintMaker with the callee view.
* Any constraints defined are added to the view or the appropriate superview once the block has finished executing
*
* @param block scope within which you can build up the constraints which you wish to apply to the view.
*
* @return Array of created MASConstraints
*/
- (NSArray *)mas_makeConstraints:(void(^)(MASConstraintMaker *make))block;
/**
* Creates a MASConstraintMaker with the callee view.
* Any constraints defined are added to the view or the appropriate superview once the block has finished executing.
* If an existing constraint exists then it will be updated instead.
*
* @param block scope within which you can build up the constraints which you wish to apply to the view.
*
* @return Array of created/updated MASConstraints
*/
- (NSArray *)mas_updateConstraints:(void(^)(MASConstraintMaker *make))block;
/**
* Creates a MASConstraintMaker with the callee view.
* Any constraints defined are added to the view or the appropriate superview once the block has finished executing.
* All constraints previously installed for the view will be removed.
*
* @param block scope within which you can build up the constraints which you wish to apply to the view.
*
* @return Array of created/updated MASConstraints
*/
- (NSArray *)mas_remakeConstraints:(void(^)(MASConstraintMaker *make))block;
总的来说,mas_makeConstraints
就是在原基础上添加约束,mas_updateConstraints
就是更新约束,mas_remakeConstraints
就是先去除原有约束再添加约束
总结
- 先把要添加约束的控件add到父视图上(addSubview)
- 使用mas_makeConstraints添加约束,make可以设想成这个控件本身
- 如果是添加左侧或者上侧的约束,offset用正数,如果添加右侧和下侧的约束,offset用负数
- 设置本身的约束(height、width)用mas_equalTo
- 如果两个平级控件之间设置约束,第二个控件要带上(mas_方向)
我是翻滚的牛宝宝,欢迎大家评论交流~