Masonry是一个轻量级的封装了Autolayout框架
https://github.com/Masonry/Masonry
github页面上给出了使用Masonry和Autolayout实现同样效果代码量的对比
当然了你如果学习了VFL,代码量也不会很多
平常我们使用Autolayout要设置view.translatesAutoresizingMaskIntoConstraints = NO;
Masonry会自动帮我们调用这行代码
结合官方的实例看几个小时差不多就能使用Masonry了,
UIEdgeInsets padding = UIEdgeInsetsMake(10, 10, 10, 10);
[view1 mas_makeConstraints:^(MASConstraintMaker *make) { make.top.equalTo(superview.mas_top).with.offset(padding.top); //with is an optional semantic filler make.left.equalTo(superview.mas_left).with.offset(padding.left); make.bottom.equalTo(superview.mas_bottom).with.offset(-padding.bottom); make.right.equalTo(superview.mas_right).with.offset(-padding.right); }];
让一个在父视图上上下左右各缩进10个长度(请自动脑补如果使用Autolayout的代码量)
下面是效果图
或者你可以用一行代码搞定上面的效果图
[view1 mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(superview).with.insets(padding);
}];
肿么样,给力吧
除了可以使用make.edges还可以使用make.size等,直接设置size约束
Masonry还会自动识别你要设置的属性(上,下,左,右),下面两行代码的效果等价
make.left.greaterThanOrEqualTo(label);
make.left.greaterThanOrEqualTo(label.mas_left);
下面是宽度约束的代码
make.width.greaterThanOrEqualTo(@200); make.width.lessThanOrEqualTo(@400)
然而,Autolayout不允许对齐元素(left ,centerX)等写成常量 ,所以如果你写成下面那句代码
make.left.lessThanOrEqualTo(@10)
Masonry会自动帮你转换为下面的约束式(关联superView)
view.left = view.superview.left + 10
你出了可以使用NSNumber,还可以使用基本类型量和结构体(最下面那句代码是多次设置)
make.top.mas_equalTo(42); make.height.mas_equalTo(20); make.size.mas_equalTo(CGSizeMake(50, 100)); make.edges.mas_equalTo(UIEdgeInsetsMake(10, 0, 10, 0)); make.left.mas_equalTo(view).mas_offset(UIEdgeInsetsMake(10, 0, 10, 0));
此外你还可以添加NSArray(一组)约束
make.height.equalTo(@[view1.mas_height, view2.mas_height]); make.height.equalTo(@[view1, view2]); make.left.equalTo(@[view1, @100, view3.right]);
还可以一次添加多个约束,使用链式语句或者结构体
Masonry also gives you a few convenience methods which create multiple constraints at the same time. These are called MASCompositeConstraints edges // make top, left, bottom, right equal view2 make.edges.equalTo(view2); // make top = superview.top + 5, left = superview.left + 10, // bottom = superview.bottom - 15, right = superview.right - 20 make.edges.equalTo(superview).insets(UIEdgeInsetsMake(5, 10, 15, 20)) size // make width and height greater than or equal to titleLabel make.size.greaterThanOrEqualTo(titleLabel) // make width = superview.width + 100, height = superview.height - 50 make.size.equalTo(superview).sizeOffset(CGSizeMake(100, -50)) center // make centerX and centerY = button1 make.center.equalTo(button1) // make centerX = superview.centerX - 5, centerY = superview.centerY + 10 make.center.equalTo(superview).centerOffset(CGPointMake(-5, 10)) You can chain view attributes for increased readability: // All edges but the top should equal those of the superview make.left.right.and.bottom.equalTo(superview); make.top.equalTo(otherView);
你还可以定义约束的优先级,当约束出现冲突的时候,优先级高的约束覆盖优先级低的约束(下面的代码是添加优先级)
make.left.greaterThanOrEqualTo(label.mas_left).with.priorityLow(); make.top.equalTo(label.mas_top).with.priority(600);
有时候我们需要去掉某些约束,或者修改某些约束(动画等),这个时候肿么办呢?
// in public/private interface @property (nonatomic, strong) MASConstraint *topConstraint; ... // when making constraints [view1 mas_makeConstraints:^(MASConstraintMaker *make) { self.topConstraint = make.top.equalTo(superview.mas_top).with.offset(padding.top); make.left.equalTo(superview.mas_left).with.offset(padding.left); }]; ... // then later you can call [self.topConstraint uninstall];
使用一个引用,在不需要的时候,调用uninstall就可以去掉约束了
如果你后续需要改变约束(添加动画等),你可以调用另外一个创建约束的方法,并把约束需要的值,写成变量(苹果建议添加个更新约束写在updateConstraints方法中)
// this is Apple's recommended place for adding/updating constraints // this method can get called multiple times in response to setNeedsUpdateConstraints // which can be called by UIKit internally or in your code if you need to trigger an update to your constraints - (void)updateConstraints { [self.growingButton mas_updateConstraints:^(MASConstraintMaker *make) { make.center.equalTo(self); make.width.equalTo(@(self.buttonSize.width)).priorityLow(); make.height.equalTo(@(self.buttonSize.height)).priorityLow(); make.width.lessThanOrEqualTo(self); make.height.lessThanOrEqualTo(self); }]; //according to apple super should be called at end of method [super updateConstraints]; }
有时候我们为了改变约束,需要有变量来引用约束,这个时候如果需要改变的约束非常多,那么这将是一个非常蛋疼的代码量
所以Masonry提供了一个重建约束的方法,使用这个方法,建立约束之前会把之前的约束全部清除掉,然后重新添加,这样我们只需要添加执行逻辑代码就行了(判断等)
如下
mas_updateConstraints is useful for updating a set of constraints, but doing anything beyond updating constant values can get exhausting. That's where mas_remakeConstraints comes in. mas_remakeConstraints is similar to mas_updateConstraints, but instead of updating constant values, it will remove all of its contraints before installing them again. This lets you provide different constraints without having to keep around references to ones which you want to remove. - (void)changeButtonPosition { [self.button mas_remakeConstraints:^(MASConstraintMaker *make) { make.size.equalTo(self.buttonSize); if (topLeft) { make.top.and.left.offset(10); } else { make.bottom.and.right.offset(-10); } }]; }
约束出现问题的时候控制台打印的信息过于笼统,不容易让人发现问题,为此Masonry,添加了分类,重写了约束的description方法
从而可以给出更详细的提示信息
Masonry adds a category to NSLayoutConstraint which overrides the default implementation of - (NSString *)description. Now you can give meaningful names to views and constraints, and also easily pick out the constraints created by Masonry.
Masonry还给出了snippets
Copy the included code snippets to ~/Library/Developer/Xcode/UserData/CodeSnippets to write your masonry blocks at lightning speed! mas_make -> [<view> mas_makeConstraints:^(MASConstraintMaker *make){<code>}]; mas_update -> [<view> mas_updateConstraints:^(MASConstraintMaker *make){<code>}]; mas_remake -> [<view> mas_remakeConstraints:^(MASConstraintMaker *make){<code>}];