Masonry 到底有多美?

Autolayout就像一个知情达理,善解人意的好姑娘,可惜长相有点不堪入目,所以追求者寥寥无几。所幸遇到了化妆大师cloudkite,给她来了一个完美的化妆,从此丑小鸭Autolayout变成了美天鹅Masonry。前几日有幸一见,果然名不虚传,长相甜美,还善解人意。我果断放弃了Frame,开始追求Masonry。

初识Masonry

初见

我们先来看看Masonry到底有多美。

我要设置一个containView,他距离superView的上下左右边距都是10。 如果我用frame,应该是这样写的:

UIEdgeInsetsedge = UIEdgeInsetsMake(10,10,10,10);

CGSizesuperSize = view.superview.frame.size;

CGFloatwidth = superSize.width - edge.left - edge.right;

CGFloatheitht = superSize.height - edge.top - edge.bottom;

view.frame = CGRectMake(edge.left,edge.top,width,heitht);

逻辑比较复杂,阅读的时候还得想半天才能想明白,这个frame到底要表达的是什么意思。而且关键的是父View的大小如果改变,还需要再次重新设置Frame。看着Frame这黄脸婆,心里一阵别扭…

我们来看看充满青春活力的小鲜肉Masonry是怎么样的:

UIEdgeInsetsedge = UIEdgeInsetsMake(10,10,10,10);

[view mas_makeConstraints:^(MASConstraintMaker*make){

make.edges.equalTo(view.superview).insets(edge);

}];

使用mas_makeConstraints在block中对View添加约束。view相对父View的边距为edge。

代码简单,逻辑一目了然。而且还能跟父View一起调整。简直是perfect,初见Masonry,惊为天人

细品

cloudkite给Autolayout披上一层漂亮的外衣之后,将其称为Masonry,但Masonry的本质还是Autolayout。

Autolayout是什么呢?Autolayout就是给View添加一堆约束,让View在布局的时候通过约束计算出Frame,然后进行布局(Autolayout更多内容见Autolayout的第一次亲密接触)。make.edges.equalTo(view.superview).insets(edge);就是添加约束的过程。

对于一个约束。他实际表示的是一个不等或者相等关系

Masonry 到底有多美?

用Masonry创建一个完整的约束应该是这样的

//view1的左边距离父View左边10个点:

[view1 mas_makeConstraints:^(MASConstraintMaker*make){

make.left.equalTo(view1.superview.mas_left).multipliedBy(1).offset(10);

}];

对应到上图的表达式:

Attribute

MASConstraintMaker

上面的表达式中,我们可以看到,make是MASConstraintMaker类型。MASConstraintMaker给我们提供了22种Attribute类型

//Basic Attribute

@property(nonatomic,strong,readonly)MASConstraint*left;

@property(nonatomic,strong,readonly)MASConstraint*top;

@property(nonatomic,strong,readonly)MASConstraint*right;

@property(nonatomic,strong,readonly)MASConstraint*bottom;

@property(nonatomic,strong,readonly)MASConstraint*leading;

@property(nonatomic,strong,readonly)MASConstraint*trailing;

@property(nonatomic,strong,readonly)MASConstraint*width;

@property(nonatomic,strong,readonly)MASConstraint*height;

@property(nonatomic,strong,readonly)MASConstraint*centerX;

@property(nonatomic,strong,readonly)MASConstraint*centerY;

@property(nonatomic,strong,readonly)MASConstraint*baseline;

//Margin Attribute

@property(nonatomic,strong,readonly)MASConstraint*leftMargin;

@property(nonatomic,strong,readonly)MASConstraint*rightMargin;

@property(nonatomic,strong,readonly)MASConstraint*topMargin;

@property(nonatomic,strong,readonly)MASConstraint*bottomMargin;

@property(nonatomic,strong,readonly)MASConstraint*leadingMargin;

@property(nonatomic,strong,readonly)MASConstraint*trailingMargin;

@property(nonatomic,strong,readonly)MASConstraint*centerXWithinMargins;

@property(nonatomic,strong,readonly)MASConstraint*centerYWithinMargins;

//Convenient Attribute

@property(nonatomic,strong,readonly)MASConstraint*edges;

@property(nonatomic,strong,readonly)MASConstraint*size;

@property(nonatomic,strong,readonly)MASConstraint*center;

Attribute总体来说分为三大类

Convenient Attribute实际是基本属性的组合。比如:edges表示left, right, top, bottom。

下面的两个代码实际的意义是一样的

//Convenient Attribute

make.edges.insets(edge);

//Basic Attribute

make.left.right.top.bottom.insets(edge);

MASConstraint

前面我们看到MASConstraintMaker中所有的Attribute都是MASConstraint类型。对于多个Attribute一起写的表达式:

make.left.right.top.bottom.insets(edge);

make.left返回的已经是MASConstraint类型,也就是说right这个Attribute是MASConstraint的属性。

MASConstraint给我们提供了19种Attribute:

//Basic Attribute

@property(nonatomic,strong,readonly)MASConstraint*left;

@property(nonatomic,strong,readonly)MASConstraint*top;

@property(nonatomic,strong,readonly)MASConstraint*right;

@property(nonatomic,strong,readonly)MASConstraint*bottom;

@property(nonatomic,strong,readonly)MASConstraint*leading;

@property(nonatomic,strong,readonly)MASConstraint*trailing;

@property(nonatomic,strong,readonly)MASConstraint*width;

@property(nonatomic,strong,readonly)MASConstraint*height;

@property(nonatomic,strong,readonly)MASConstraint*centerX;

@property(nonatomic,strong,readonly)MASConstraint*centerY;

@property(nonatomic,strong,readonly)MASConstraint*baseline;

//Margin Attribute

@property(nonatomic,strong,readonly)MASConstraint*leftMargin;

@property(nonatomic,strong,readonly)MASConstraint*rightMargin;

@property(nonatomic,strong,readonly)MASConstraint*topMargin;

@property(nonatomic,strong,readonly)MASConstraint*bottomMargin;

@property(nonatomic,strong,readonly)MASConstraint*leadingMargin;

@property(nonatomic,strong,readonly)MASConstraint*trailingMargin;

@property(nonatomic,strong,readonly)MASConstraint*centerXWithinMargins;

@property(nonatomic,strong,readonly)MASConstraint*centerYWithinMargins;

细看一下,MASConstraint中的Attribute和MASConstraintMaker完全一样。只是MASConstraintMaker中多了3种Convenient Attribute。

两者Attribute的一致,大大的提升了使用的方便性。使用过程中我们不用再去区分当前属性是MASConstraint还是MASConstraintMaker类型。(事实上没研究他的类型之前,我都不知道他们分别属于2种不同类的属性)

UIView(12月7日新增)

我们可以看到在.equalTo(view1.superview.mas_left)里面,superView也有Attribute。我们来看看UIView中有哪些Attribute:

// Basic Attribute

@property(nonatomic,strong,readonly)MASViewAttribute*mas_left;

@property(nonatomic,strong,readonly)MASViewAttribute*mas_top;

@property(nonatomic,strong,readonly)MASViewAttribute*mas_right;

@property(nonatomic,strong,readonly)MASViewAttribute*mas_bottom;

@property(nonatomic,strong,readonly)MASViewAttribute*mas_leading;

@property(nonatomic,strong,readonly)MASViewAttribute*mas_trailing;

@property(nonatomic,strong,readonly)MASViewAttribute*mas_width;

@property(nonatomic,strong,readonly)MASViewAttribute*mas_height;

@property(nonatomic,strong,readonly)MASViewAttribute*mas_centerX;

@property(nonatomic,strong,readonly)MASViewAttribute*mas_centerY;

@property(nonatomic,strong,readonly)MASViewAttribute*mas_baseline;

// Margin Attribute

@property(nonatomic,strong,readonly)MASViewAttribute*mas_leftMargin;

@property(nonatomic,strong,readonly)MASViewAttribute*mas_rightMargin;

@property(nonatomic,strong,readonly)MASViewAttribute*mas_topMargin;

@property(nonatomic,strong,readonly)MASViewAttribute*mas_bottomMargin;

@property(nonatomic,strong,readonly)MASViewAttribute*mas_leadingMargin;

@property(nonatomic,strong,readonly)MASViewAttribute*mas_trailingMargin;

@property(nonatomic,strong,readonly)MASViewAttribute*mas_centerXWithinMargins;

@property(nonatomic,strong,readonly)MASViewAttribute*mas_centerYWithinMargins;

可以看出,在UIView中的Attribute和MASConstraint中的几乎一模一样,只是每一个Attribute加了一个mas_前缀。

由于UIView是系统的类,对其扩展属性和方法一般都需要添加自己的前缀,避免跟原有属性和方法冲突。不过他们的意义跟MASConstraint中的Attribute是相同的

Relationship

约束表示的是2个item之间的关系,在Autolayout中一共定义了3种关系:=, >=, <=,对应到Masonry中:

- (MASConstraint * (^)(idattr))equalTo;

- (MASConstraint * (^)(idattr))greaterThanOrEqualTo;

- (MASConstraint * (^)(idattr))lessThanOrEqualTo;

相等关系我们一般用的多。那么不相等关系我们什么时候用呢?

假如我有一个Label。Label的长度不能超出父View,如果label中的文字比较短,我希望是文字有多长,Label就有多长。

由于label具有IntrinsicContentSize属性。所以默认情况下,他是文字有多长,Label就有多长。(更多IntrinsicContentSize的内容参见Autolayout的第一次亲密接触)。所以我们只需要设置Label的长度小于父View即可

[label mas_makeConstraints:^(MASConstraintMaker*make){

make.left.offset(0);

make.centerY.offset(0);

make.width.lessThanOrEqualTo(label.superview);

}];

multiplier

multiplier表示Attribute前面的乘数。Masonry提供了2种添加multiplier的方法

// Sets the NSLayoutConstraint multiplier property

- (MASConstraint * (^)(CGFloatmultiplier))multipliedBy;

// Sets the NSLayoutConstraint multiplier to 1.0/pidedBy

- (MASConstraint * (^)(CGFloatpider))pidedBy;

Constant

Masonry提供了4种设置constant的方法

//Modifies the NSLayoutConstraint constant,only affects MASConstraints in which the first item's NSLayoutAttribute is one of the following NSLayoutAttributeTop, NSLayoutAttributeLeft, NSLayoutAttributeBottom, NSLayoutAttributeRight

- (MASConstraint * (^)(MASEdgeInsetsinsets))insets;

//Modifies the NSLayoutConstraint constant,only affects MASConstraints in which the first item's NSLayoutAttribute is one of the following NSLayoutAttributeWidth, NSLayoutAttributeHeight

- (MASConstraint * (^)(CGSizeoffset))sizeOffset;

//Modifies the NSLayoutConstraint constant, only affects MASConstraints in which the first item's NSLayoutAttribute is one of the following NSLayoutAttributeCenterX, NSLayoutAttributeCenterY

- (MASConstraint * (^)(CGPointoffset))centerOffset;

//Modifies the NSLayoutConstraint constant

- (MASConstraint * (^)(CGFloatoffset))offset;

其实一般情况下,我只使用offset….

小技巧

下面所有代码实际效果是一样的:

// 完整的

make.left.equalTo(view1.superview.mas_left).offset(0);

//省略Attribute的

make.left.equalTo(view1.superview).offset(0);

//省略equalTo的

make.left.offset(0);

//使用equalTo替代offset的

make.left.equalTo(@0);

//终极大招,省略所有的... 可惜会有warning

make.left;

不过对于make.left,编译器会报一个警告:你用getter方法获取回来的值未使用,所以不应该使用”.”语法

Masonry 到底有多美?

对于这个警告我们可以将返回值转为空消除:

(void)make.left;

不过终究又变得麻烦了,又要多写6个字母,愁人…

设置或更新约束

对于约束的设置,Masonry提供了3种方法,分别为设置约束、更新约束、重写设置约束

// 设置约束

- (NSArray*)mas_makeConstraints:(void(^)(MASConstraintMaker*make))block;

// 更新约束

- (NSArray*)mas_updateConstraints:(void(^)(MASConstraintMaker*make))block;

// 重新设置约束

- (NSArray*)mas_remakeConstraints:(void(^)(MASConstraintMaker*make))block;

注意:mas_updateConstraints只能更新已有约束。如果第一次使用的是left, right设置的相对宽度。更新的时候想换成使用width。不能使用mas_updateConstraints,因为已有约束里面没有width的约束,新增width之后会跟原有left, right约束冲突。此时应该使用mas_remakeConstraints

批量设置约束

假设有View1,view2,view3三个View,我们想要他们的宽高都等于CGSizeMake(100, 50)。我们可以对他们进行批量设置:

NSValue*sizeValue = [NSValue valueWithCGSize:CGSizeMake(100,50)];

[@[view1,view2,view3] mas_makeConstraints:^(MASConstraintMaker*make){

make.size.equalTo(sizeValue);

}];

由于我们还要设置view的top,left等位置约束。那可不可以在设置位置的mas_makeConstraints里面批量设置宽高呢?实际是可以的!

//advance set

[view1 mas_makeConstraints:^(MASConstraintMaker*make){

(void)make.top.left;

make.size.equalTo(@[view2,view3,sizeValue]);

}];

不过需要注意的是。设置约束的时候,view一定是已经被addSubview的(详情参考Autolayout的第一次亲密接触),否则会抛异常。所以我们一般在最后一个view上加批量约束

Priority

我们知道约束是有优先级的,Masonry给我们提供了4个设置优先级的接口:

// Sets the NSLayoutConstraint priority to a float or MASLayoutPriority

- (MASConstraint * (^)(MASLayoutPrioritypriority))priority;

// Sets the NSLayoutConstraint priority to MASLayoutPriorityLow

- (MASConstraint * (^)())priorityLow;

// Sets the NSLayoutConstraint priority to MASLayoutPriorityMedium

- (MASConstraint * (^)())priorityMedium;

// Sets the NSLayoutConstraint priority to MASLayoutPriorityHigh

- (MASConstraint * (^)())priorityHigh;

需要注意的是,使用priorityLow、priorityMedium、priorityHigh的时候。不是.priorityHigh,而是.priorityHigh()

展开阅读全文

页面更新:2024-03-16

标签:会报   知情达理   乘数   等式   前缀   优先级   表达式   善解人意   批量   属性   类型   文字   代码   关系   方法   科技

1 2 3 4 5

上滑加载更多 ↓
推荐阅读:
友情链接:
更多:

本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828  

© CopyRight 2020-2024 All Rights Reserved. Powered By 71396.com 闽ICP备11008920号-4
闽公网安备35020302034903号

Top