iOS-Masonry学习笔记

Masonry目前是Github上很热门的iOS开源项目之一。它是一个轻量级的布局框架,比AutoLayout使用起来更简便。它还有自己的一套DSL,提供了链式的方式来描述传统的NSLayoutConstraint布局。我们将会看到使用Masonry的代码会更简介紧凑,拥有更好的可读性,并且它支持iOSMac OS X平台。

NSLayoutConstraint的缺点

  之前在对AutoLayout进行了解的时候已经对NSLayoutConstraint进行了简单的应用说明,传送门——iOS-AutoLayout布局学习。我们会发现虽然它可以很灵活的进行约束布局,但是给某个视图创建特定的约束的代码量是比较冗长的。
  我们可以想象到在实际项目中视图会很多,此时光是给视图进行约束的代码量就会很大,这样大大降低了代码的可读性,增加了代码维护的成本。可能我们会想到使用VFS来减少代码量,但是这种做法使的我们难以对视图的动画进行控制。

初遇 Maker

  首先先来个简单的小例子来使用一下MASConstraintMaker,首先要实现的效果就是一个视图相对父视图四周边距均为50。想象一下如果使用NSLayoutConstraint我们将会创建四个边界的约束,然后添加到父视图中。然而我们现在使用了Masonry后则会大大简化代码。

UIEdgeInsets padding = UIEdgeInsetsMake(50, 50, 50, 50);
//添加约束
[self.view1 mas_makeConstraints:^(MASConstraintMaker *make) {
    make.top.equalTo(self.view.mas_top).with.offset(padding.top);
    make.left.equalTo(self.view.mas_left).with.offset(padding.left);
    make.bottom.equalTo(self.view.mas_bottom).with.offset(-padding.bottom);
    make.right.equalTo(self.view.mas_right).with.offset(-padding.right);
}];

  从代码中我们可以看到,通过MASConstraintMaker我们可以简单的创建针对四边边距的约束,而且语义比较容易理解,这种链式的表达方式也正式Masonry的特色之一。其实还有更简单的方法来设置边距。

[self.view1 mas_makeConstraints:^(MASConstraintMaker *make) {
    make.edges.equalTo(self.view).with.insets(padding);
}];

对比

.equalTo = NSLayoutRelationEqual

.lessThanOrEqualTo = NSLayoutRelationLessThanOrEqual

.greaterThanOrEqualTo = NSLayoutRelationGreaterThanOrEqual

以下是两种约束方式的对应属性表格。

更多使用

Edge

  我们来在以上view1的基础上再添加一个子视图view2,来简单介绍一下MASConstraintMaker相关属性的约束方式。
  如果我们想简单的让某个视图的某个属性的约束等于另一个属性,则可以这样设置。比如我们这你将设置view2的边距属性和view1一样。然后我们就会看到view2完全覆盖在view1之上。

[self.view2 mas_makeConstraints:^(MASConstraintMaker *make) {
    //edge的设置
    make.edges.equalTo(self.view1);
    //这个设置则会使得view2距离view1的边距为10
    //make.edges.equalTo(self.view1).insets(UIEdgeInsetsMake(10, 10, 10, 10));
}];

Size

在实际应用中我们可能还是涉及设定某个视图的大小,那么就需要约束该视图的size属性了。但是需要注意的是只设置视图的size属性的话只能设置该视图的大小而已,如果还要约束它和其他视图的相对位置则需要其他的属性约束,一般结合edge,center等属性一起设置。
比如我们先设置view2为一个size等于view1的视图。效果如图。

[self.view2 mas_makeConstraints:^(MASConstraintMaker *make) {
    make.size.equalTo(self.view1);
    //这个设置为view2大小在view1大小基础上宽和高各减100
    //make.size.equalTo(self.view1).sizeOffset(CGSizeMake(-100, -100));
}];

我们可以从图中看出,view2只是size大小等于view1而已,而位置则是没有约束的。

Center

center属性是用来设置子视图相对父视图居中的。当然还可以在居中的基础上进行一定的偏移。只设置center属性时候是不足以约束视图的,我们可以想象一下我们只是说明了子视图相对父视图是居中的,但没有足够的条件计算子视图的宽度和高度,所以往往也是要结合size和edge等属性一起设置的。
接下来我们给出一个例子即让一个宽高比view1各小100的view2子视图在父视图view1中居中显示。

[self.view2 mas_makeConstraints:^(MASConstraintMaker *make) {
    make.size.equalTo(self.view1).sizeOffset(CGSizeMake(-100, -100));
    make.center.equalTo(self.view1);
    //这个设置说明view2相对于view1的中心向左上方x,y方向偏移20
    //make.center.equalTo(self.view1).centerOffset(CGPointMake(-20, -20));
}];

效果如下图。

链式属性设置

链式属性设置是Masonry的一个特色,使用链式属性的话可以更方便的设置某些拥有相等值的属性。比如下面的例子就设置视图四边的边距,而对于特定的top属性由于它与其他并不同可以单独设置。而其他三边值是相等的我们没必要写三行代码来进行设置。其中的and其实现实际只是返回对象本身而已,在这里起了语义连贯的作业,也是很好玩的样子,啊哈哈哈哈哈。

make.left.bottom.and.right.equalTo(self.view1);
make.top.equalTo(@50);

总结

Masonry的使用给我们极大的简化了代码量,并且其较好的语义也使得它很容易上手。在后续的学习中也会更深入的学习它的实现原理和更高级的使用方法。大家可以参考这篇博客——Masonry介绍与使用实践:快速上手Autolayout

源代码

在项目中使用了cocoapods进行类库管理,所以clone了github上的源码之后还需要执行pod installpod update来下载依赖库。
Github项目地址:Github-iOS_UI_study-MasonryDemon

参考资料

1.Github主页 – SnapKit/Masonry
2.Masonry介绍与使用实践:快速上手Autolayout