Masonry是一个轻量级的布局框架,基于AutoLayout进行封装。简单来说就是Masonry用更简洁的语法描述了一个视图相对另一个视图的位置。
Masonry中使用了大量的点链式语法,所以有必要在读源码前了解点链式语法的基本使用
拿block里的一段代码 make.left.equalTo(superview.left).offset(padding) 分析下
- "." 相当于调用getter方法,.left相当于相当于调用了left方法,left方法定义如下
left方法有返回值,类型是 MASConstraint *
- 接下来的equalTo(superview.left),在OC语言里调用block会使用(),调用一般的方法使用的是[],equalTo()定义如下
可以看到equalTo()也是返回block,block有类型也是 MASConstraint * 的返回值
- 接下来的offset(padding) 原理跟equalTo(superview.left) 是一样的
从2,3两点可以看出,在每次调用完block后如果返回调用者对象本身,就可以实现的调用了。
Masonry文件列表如下:
从最基本的使用开始探究代码的流程
- makeConstraints
在这里创建MASConstraintMaker * 对象,用来管理block里的像NSLayoutAttributeLeft 等这些属性,和创建约束。
- make.left
继续往下查看
- 根据传进来的参数layoutAttribute 生成MASViewConstraint * 对象
- 如果链式语法像make.left.right 这样调用就会进入这里,生成复合型约束MASCompositeConstraint * 对象
- 链式调用的初始调用会进入这里,像make.left
总结来说make.left 做的事情是根据NSLayoutAttribute属性创建并返回MASViewConstraint * 对象
- make.left.equalTo(superview.left)
equalTo()的定义如下:
继续往下查看
这里要做的事情就是给layoutRelation 和secondViewAttribute 这两个属性赋值,着重看一下secondViewAttribute 的赋值操作
- 如果superview.left 传入的是数字
- 如果superview.left 传入的是UIView类,就设置secondViewAttribute的layoutAttribute和firstViewAttribute的layoutAttribute一样
- 如果superview.left 传入的是MASViewAttribute类,直接赋值
总结一下,首先自动布局有一个公式item1.attribute1 = multiplier × item2.attribute2 + constant ,make.left 创建了一个firstViewAttribute,firstViewAttribute 的view属性,相当于封装了布局公式的左边;而equalTo() 则是将secondViewAttribute 赋值给MASViewConstraint 对象的secondViewAttribute 属性,并给MASViewConstraint 对象的layoutRelation 属性赋值,相当于封装了布局公式的右边
- offset()
这里的逻辑也很简单,就是给MASViewConstraint 对象的layoutConstant 属性赋值
到这里make.left.equalTo(superview.left).offset(padding) 的代码流程就解读完了
- [constraintMaker install]
这个方法就是将我们前面编好的约束添加到视图上
前面类似.left和.left.right都会将约束MASConstraint 对象加到一个数组里,执行install方法就会遍历数组里每个约束,将约束添加到视图上
继续往下查看
- 若firstView 和 secondView 有共同的父视图,则将约束添加到父视图上
- 若约束是size的约束(即width和height),则将约束添加到本视图
- 否则将约束添加到本视图的父视图
- 最后把约束添加到视图上
整体上Masonry的代码设计并不复杂,框架工整,通过一层一层地继承,让每一层的子类各司其职,而且像对bug的跟踪和断言的使用,非常值得参考学习。