Masonry是一个轻量级的布局框架。通过链式调用的方式来描述布局,是排版代码更加简洁易读。masonry支持iOS和Mac OS X。相比原生的NSLayoutConstraint,提高了使用容易度和代码的可阅读程度。Masonry使用了链式语法,
使用原生的NSLayoutConstraint进行布局时,十分冗杂麻烦,这里给出一个例子进行演示。
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];
UIView* iview = [[UIView alloc] init];
iview.backgroundColor = [UIColor redColor];
iview.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview:iview];
[self.view addConstraints:@[
[NSLayoutConstraint constraintWithItem:iview attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationLessThanOrEqual toItem:self.view attribute:NSLayoutAttributeLeft multiplier:0.5 constant:40],
[NSLayoutConstraint constraintWithItem:iview attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationLessThanOrEqual toItem:self.view attribute:NSLayoutAttributeTop multiplier:1.0 constant:40],
[NSLayoutConstraint constraintWithItem:iview attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeBottom multiplier:1.0 constant:-40],
[NSLayoutConstraint constraintWithItem:iview attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeRight multiplier:1.0 constant:-40],
]];
}
在这个例子中使用了+ (instancetype)constraintWithItem:(id)view1 attribute:(NSLayoutAttribute)attr1 relatedBy:(NSLayoutRelation)relation toItem:(nullable id)view2 attribute:(NSLayoutAttribute)attr2 multiplier:(CGFloat)multiplier constant:(CGFloat)c
这个方法,下面讲解一下这个方法的使用。
+ (instancetype)constraintWithItem:(id)view1 //指定了第一个视图,也就是要应用约束的视图。
attribute:(NSLayoutAttribute)attr1 //指定了要应用于第一个视图的属性,比如 NSLayoutAttributeLeft、NSLayoutAttributeTop 等。
relatedBy:(NSLayoutRelation)relation //指定了约束的关系,可以是 NSLayoutRelationEqual、NSLayoutRelationGreatherThanOrEqual 或 NSLayoutRelationLessThanOrEqual。
toItem:(nullable id)view2 //指定了第二个视图,也就是第一个视图要相对于哪个视图进行约束。如果为 nil,则表示约束是相对于父视图进行的。
attribute:(NSLayoutAttribute)attr2 //指定了第二个视图的属性,用于与第一个视图的属性进行约束。
multiplier:(CGFloat)multiplier //指定了第一个视图的属性和第二个视图的属性之间的乘数关系。例如,如果设置为 2.0,则表示第一个视图的属性是第二个视图的属性的 2 倍。(不太理解这个的意思)
constant:(CGFloat)c//指定了常量偏移量,用于调整约束的位置或大小
由上面这个例子可以看出,在使用传统的api约束时十分麻烦,故而学习使用Masorny进行约束,简化步骤。
下面先给出一个对照的表格,后期可以使用进行参考。
MASViewAttribute | NSLayoutAttribute |
---|---|
view.mas_left | NSLayoutAttributeLeft |
view.mas_right | NSLayoutAttributeRight |
view.mas_top | NSLayoutAttributeTop |
view.mas_bottom | NSLayoutAttributeBottom |
view.mas_leading | NSLayoutAttributeLeading |
view.mas_trailing | NSLayoutAttributeTrailing |
view.mas_width | NSLayoutAttributeWidth |
view.mas_height | NSLayoutAttributeHeight |
view.mas_centerX | NSLayoutAttributeCenterX |
view.mas_centerY | NSLayoutAttributeCenterY |
view.mas_baseline | NSLayoutAttributeBaseLine |
使用MASConstraintMaker实现和上面例子一样的约束:
_view1 = [[UIView alloc] init];
_view1.backgroundColor = [UIColor greenColor];
[self.view addSubview:_view1];
[_view1 mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.mas_equalTo(40);
make.top.mas_equalTo(40);
make.bottom.mas_equalTo(-40);
make.right.mas_equalTo(-40);
}];
不难看出,代码量减少了很多,masonry会自动添加约束到合适的视图,也会为你调用view1.translatesAutoresizingMaskIntoConstraints = NO。
首先可以确定的是这两者是等价的,其中mas_equalTo支持的类型,除了NSNumber支持的那些数值类型之外 就只支持CGPoint、CGSize、UIEdgeInsets,而equalTo支持的类型为id。
make.right.mas_equalTo(-40)
make.right.equalTo(@-40);
实际使用中两者的效果是相同的。可以参考这篇博客Mansory之一 :mas_equalTo和equalTo区别与使用。
priority:允许你指定一个确切的优先级。
priorityHigh:同UILayoutPriorityDefaultHigh。
priorityMedium:介于高和低之间的优先级。
priorityLow:同UILayoutPriorityDefaultLow。
优先级可以追加到约束链的末尾,下面给出一个例子:
make.bottom.mas_equalTo(-40).with.priorityHigh();
make.right.mas_equalTo(-40).with.priorityLow();
[_view1 mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.mas_equalTo(self.view).mas_offset(40);
make.top.mas_equalTo(self.view).mas_offset(40);
make.bottom.mas_equalTo(self.view).mas_offset(-40);
make.right.mas_equalTo(self.view).mas_offset(-40);
}];
在这种写法中,先指定了相对于约束的视图,而后对现在的视图进行约束。在使用前文中使用的写法时,要注意先对视图添加到父视图中,系统会自动对父视图进行约束视图,否则会出现报错,由于没有父视图。
这里举出了一个由父视图位置移动而影响子视图的例子,通过点击按钮更新view1的位置,从而由他对按钮的约束来影响按钮的位置。
-(void) press {
if(_btn.selected == NO) {
[_view1 mas_updateConstraints:^(MASConstraintMaker *make) {
make.left.mas_equalTo(self.view).mas_offset(40);
make.top.mas_equalTo(self.view).mas_offset(100);
make.bottom.mas_equalTo(self.view).mas_offset(-40);
make.right.mas_equalTo(self.view).mas_offset(-40);
}];
_btn.selected = YES;
} else {
[_view1 mas_updateConstraints:^(MASConstraintMaker *make) {
make.left.mas_equalTo(self.view).mas_offset(40);
make.top.mas_equalTo(self.view).mas_offset(40);
make.bottom.mas_equalTo(self.view).mas_offset(-40);
make.right.mas_equalTo(self.view).mas_offset(-40);
}];
_btn.selected = NO;
}
}
这里对Masonry进行更新约束,可以看看这两篇博客Masonry学习之更新约束、【iOS】Masonry如何动态更新约束的优先级(priority)这里我还没有完全理解,后期理解了再进行补充。
参考博客:
Masonry使用指南