项目Github地址
Masonry 的 使用
做过iOS的对Masonry这个库应该都会比较熟悉,其主要原理是对苹果原生的Autolayout进行了一套封装,提供更加易用的API给使用者使用。相对于苹果原生的Autolayout,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);
}];
部分约束能提供更简洁的写法
[view1 mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(superview).with.insets(padding);
}];
Masonry 的 缺点
尽管Masonry的写法相对苹果原生Autolayout来说是一个很大的进步,但是带来一些缺点,例如Masonry的使用给界面布局带来大量重复的胶水代码。
举个demo例子:
Masonry写法:
[scrollView mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.left.right.bottom.mas_equalTo(0);
}];
[viewA mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.mas_equalTo(0);
make.left.mas_equalTo(10);
make.width.mas_equalTo(300);
make.height.mas_equalTo(310);
}];
[viewB mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.mas_equalTo(viewA.mas_bottom).offset(50);
make.left.mas_equalTo(10);
make.width.mas_equalTo(300);
make.height.mas_equalTo(300);
}];
[viewC mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.mas_equalTo(viewB.mas_bottom).offset(51);
make.left.mas_equalTo(10);
make.width.mas_equalTo(viewB).multipliedBy(0.5);
make.height.mas_equalTo(viewC).multipliedBy(2.0);
}];
[btn1 mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.mas_equalTo(viewC.mas_bottom).offset(12);
make.width.mas_equalTo(100);
make.height.mas_equalTo(50);
make.centerX.mas_equalTo(scrollView);
}];
可以看到,只是写了4个View的布局约束,就已经是30多行的代码。如果当一个界面有大量view的时候,可想而知会有多痛苦,保守估计会是:view的数量 * 6 行布局约束代码。从Masonry的代码可以看出,其存在大量重复的
mas_makeConstraints:^(MASConstraintMaker *make)
make
mas_equalTo
等描述性代码,使得整个约束设置变得臃肿,会把整个View变得Massive。
链式语法
Masonry中一个很重要的特点是链式语法,最显著的特点是xx.xx.xx的连续调用,例如
make.top.mas_equalTo(viewA.mas_bottom).offset(50);
看到这里,可能会想,能不能把Masonry用链式语法写的更简洁一点呢?
SDAutolayout的启发
SDAutolayout是一个新出的布局库,其最大特点是可以实现一行代码布局,其链式语法实现的非常优雅:
_view.sd_layout.leftSpaceToView(self.view,10).topSpaceToView(self.view,80).heightIs(130).widthRatioToView(self.view, 0.4);
哪究竟能不能像SDAutolayout一样,实现一行代码的Masonry布局呢?
新的选择 --- YKAutolayout
由于对Masonry的热爱和对Masonry胶水代码的厌恶,受SDAutolayout启发,本人选择封装Masonry的使用,自造一套模仿SDAutolayout的风格的布局工具YKAutolayout
针对上面Masonry写的demo例子,换成YKAutolayout的写法是这样的:
scrollView.yk_make.top(0).left(0);
scrollView.yk_make.right(0).bottom(0).done();
viewA.yk_make.top(33).left(10).width(310).height(310).done();
viewB.yk_make.topTo(viewA.mas_bottom,50).left(10).width(300).height(300).done();
viewC.yk_make.topTo(viewB.mas_bottom,51).left(10).widthAspectTo(viewB,0.5).heightAspectTo(viewC.mas_width,2.0)
.done();
btn1.yk_make.topTo(viewC.mas_bottom,12).width(100).height(50).centerXTo(scrollView,0).done();
相比Masonry,大大减少了胶水代码,写起来更简洁,用法也与Masonry保持一致,还能跟Masonry混编(不建议)。对于熟悉Masonry的人来说,是可以尝试一下的。
当然,有个缺点是,YKAutolayout暂时还没加上优先级的设置,对于要使用优先级的约束,还是可以使用原生Masonry来做。
YKAutolayout有个很重要特点时能跟Maosnry混编,对于一些无法使用YKAutolayout暂时无法实现的高级特性(例如约束优先级),可以使用Masonry实现。
scrollView.yk_make.top(0).left(0);
scrollView.yk_make.right(0).bottom(0).done();
viewA.yk_make.top(33).left(10).width(310).height(310).done();
[viewB mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.mas_equalTo(viewA.mas_bottom).offset(50);
make.left.mas_equalTo(10);
make.width.mas_equalTo(300);
make.height.mas_equalTo(300);
}];
viewC.yk_make.topTo(viewB.mas_bottom,51).left(10).widthAspectTo(viewB,0.5).heightAspectTo(viewC.mas_width,2.0) .done();
btn1.yk_make.topTo(viewC.mas_bottom,12).width(100).height(50).centerXTo(scrollView,0).done();
YKAutolayout 的原理
简单来说就是将top,left,width,height等属性缓存起来,在调用done函数时一次性将其放进Masonry中进行布局。而添加约束时抛弃Masonry的风格,使用SDAutolayout的风格,则能大大减少胶水代码的产生,对使用者更加友好。