iOS纯代码编写UI工具介绍:TPLayout

TPLayout简介

TPLayout是一个类似于Masonry的AutoLayout布局工具库。
它在github上的简介:

TPLayout是一个轻量、快速、方便的使用代码进行UI布局的高效率工具库。TPLayout同时支持两种常见的代码布局方式,提供非常简短的方法来获取和设置Frame值;也提供了类似Masonry的链式语句的方法来设置view的约束。

TPLayout vs Masonry, PureLayout

对于Masonry这个库大家应该都比较熟悉,就是它让大家不用去写苹果反人类的AutoLayout布局的API接口,帮助苹果普及了AutoLayout的布局方式。
对于PureLayout这个库相信应该也有大部分都知道,它将AutoLayout的接口进行了封装,也极大的方便开发者使用AutoLayout进行UI布局。
但是在使用它们的过程中,或多或少有些不方便地方。比如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);
}];

以上代码中,每条make开头语句实际上是一个约束;但是我们怎么获取到生成的约束的NSLayoutConstraint对象呢?完全没有办法,除非自己去遍历view的constraints属性。
mas_makeConstraints,mas_updateConstraints和mas_remakeConstraints三个方法把NSLayoutConstraint对象全隐藏起来了,开发者不能获取到每一个约束生成的NSLayoutConstraint对象。笔者觉得这个是Masonry库对开发者唯一不友好的地方。

再比如PureLayout:

NSLayoutConstraint *constraint =  [view autoPinEdge:ALEdgeLeft toEdge:ALEdgeLeft ofView:otherView withOffset:10];

基本上每个语句返回NSLayoutConstraint对象,但是相对于Masonry来说少了链式语句的可读性。

TPLayout库结合了两者的优点:每条链式语句返回一个NSLayoutConstraint对象或者NSLayoutConstraint对象的数组。
总结起来,TPLayout有以下特性:
- Frame: 提供简短的方法来设置view的Frame值和两个view间的对齐关系
- AutoLayout: 通过链式语句来设置view的约束
- AutoLayout: 一条链式语句生成一个NSLayoutConstraint对象或者NSLayoutConstraint对象的数组
- AutoLayout: 可以重置、更新使用该库生成的约束
- AutoLayout: 通过NSAssert断言防止X轴Y轴方向上设置错误的约束

TPLayout使用Demo

详细的Demo

使用Frame构建UI

// 设置大小
viewA.tp_size = CGSizeMake(100, 100);  

// 设置左上边距
viewA.tp_top = 10;
viewA.tp_left = 10;  

// 设置左上边距时,保持右下边距并自动调整view的size大小
viewB.tp_topResize = 10;
viewB.tp_leftResize = 10;  

// 设置左右边距距其他view的边距10px.
[viewC leftToViewLeft:otherView offset:10 fixedSize:NO];
[viewC rightToViewRight:otherView offset:-10 fixedSize:NO];

// 在其他的view中居中
[viewD centerInView:otherView]; // or
[viewD centerToView:otherView offsetSize:CGSizeZero];

// 距离其他View中心点左边10px
[viewE centerXToView:otherView offset:10]; // or
[viewE centerToView:otherView offsetSize:CGSizeMake(10,0)];

// 边距距其他view10px
[viewF edgesToView:otherView offsetEdge:UIEdgeInsetsMake(10, 10, 10, 10)];

使用AutoLayout构建UI

// 设置约束
view.al_top.greaterOrEqual(otherView.al_top).offset(10);
view.al_left.lessOrEqual(otherView.al_left).offset(10);
view.al_bottom.equal(otherview.al_top).offset(-10);
view.al_height.equal(100);
view.al_width.equal(@100);

// 设置复合属性的约束
view.al_size.equal(CGSizeMake(100,100));
view.al_center.equal(otherView).centerOffset(CGPointMake(10,10));
view.al_edges.equal(superview).insets(UIEdgeInsetsMake(10, 10, 10, 10));

// 设置约束优先级
view.al_width.priority(750).equal(@(10));

// 设置约束multiplier
view.al_width.multiplier(3).equal(otherView.al_width);

// 更新约束
view.al_width.update().lessOrEqual(superview);
// or use macros
view.al_update(al_width).lessOrEqual(superview);

// 重置约束
view.al_width.reset().lessOrEqual(superview);
// or use macros
view.al_reset(al_width).lessOrEqual(superview);

// 重置所有约束
view.al_resetAll();

可以看到,链式语句的写法和Masonry基本相同(实际上也是借鉴的Masonry库);每条语句生成一个NSLayoutConstraint对象,view的复合属性size,center,edge等,这些语句会生成一个NSLayoutConstraint对象的数组。

TPLayout的性能

大部分开发者选择开源库的一个标准就是性能。性能是很宽泛的一个概念。在这里我们主要考虑程序运行时的性能。TPLayout运行时性能应该和Masonry库不相上下,甚至会快一些,主要是少了Masonry中MASConstraintMaker,MASConstraint等一些辅助类的生成。可能有人会说Masonry是批量安装激活NSLayoutConstraint的,性能会好一些,实际上,Masonry代码中也是逐条安装激活NSLayoutConstraint。详见https://github.com/SnapKit/Masonry/blob/master/Masonry/MASConstraintMaker.m#L35

PureLayout也是每条语句生成并激活一个约束,性能和TPLayout也差不多,不过最新版的PureLayout提供了批量安装NSLayoutConstraint的API,如果用户使用这个接口来生成安装约束,性能应该会好点。详见https://github.com/PureLayout/PureLayout/blob/master/PureLayout/PureLayout/NSLayoutConstraint%2BPureLayout.h#L46