Masonry
使用
- 關(guān)鍵方法:
- (NSArray *)mas_makeConstraints:(void(^)(MASConstraintMaker *make))block;- 約束方法除了equalTo,還有l(wèi)essThanOrEqualTo和greaterThanOrEqualTo
- 當(dāng)已有約束需要更新時調(diào)用
mas_updateConstraints方法mas_remakeConstraints方法會先清除當(dāng)前所有約束再布置- Masonry的五大參數(shù):
Attribute(屬性) ,Relation(關(guān)系),Multiplier(乘),Constant(大小),Priority(優(yōu)先級)
//一個系統(tǒng)的約束創(chuàng)建方法
[NSLayoutConstraint constraintWithItem:view1
attribute:NSLayoutAttributeTop
relatedBy:NSLayoutRelationEqual
toItem:superview
attribute:NSLayoutAttributeTop
multiplier:1.0
constant:padding.top]
//mas_makeConstraints
[view1 mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(superView).with.offset(10);
make.left.equalTo(superView).with.offset(10);
make.bottom.equalTo(superView.mas_bottom).with.offset(-10);
make.right.equalTo(superView.mas_right).with.offset(-10);
// 等價于
// make.edges.equalTo(superView).with.insets(UIEdgeInsetsMake(10, 10, 10, 10));
// 會自動調(diào)用view1.translatesAutoresizingMaskIntoConstraints = NO;
}];
//mas_remakeConstrains
[self.button mas_remakeConstraints:^(MASConstraintMaker *make) {
make.size.equalTo(self.buttonSize);
if (topLeft) {
make.top.and.left.offset(10);
} else {
make.bottom.and.right.offset(-10);
}
}];
//mas_updateConstraints
[self.growingButton mas_updateConstraints:^(MASConstraintMaker *make) {
make.center.equalTo(self);
make.width.equalTo(@(self.buttonSize.width)).priorityLow();
make.height.equalTo(@(self.buttonSize.height)).priorityLow();
make.width.lessThanOrEqualTo(self);
make.height.lessThanOrEqualTo(self);
}];
//according to apple super should be called at end of method
[super updateConstraints];
}
原理
- mas_makeConstraints方法內(nèi)部創(chuàng)建MASConstraintMaker對象,然后傳遞到block執(zhí)行,完成后調(diào)用maker的install方法來確保約束被添加到視圖中
//設(shè)置約束方法
- (NSArray *)mas_updateConstraints:(void(^)(MASConstraintMaker *))block {
self.translatesAutoresizingMaskIntoConstraints = NO;
MASConstraintMaker *constraintMaker = [[MASConstraintMaker alloc] initWithView:self];
constraintMaker.updateExisting = YES;
block(constraintMaker);
return [constraintMaker install];
}
//MASConstraintMaker的install方法
- (NSArray *)install {
//判斷是否有移除所有已存在的約束標(biāo)志
if (self.removeExisting) {
NSArray *installedConstraints = [MASViewConstraint installedConstraintsForView:self.view];
for (MASConstraint *constraint in installedConstraints) {
[constraint uninstall];
}
}
//取出maker對象中的所有約束
NSArray *constraints = self.constraints.copy;
for (MASConstraint *constraint in constraints) {
//設(shè)置已經(jīng)設(shè)置了約束的標(biāo)志
constraint.updateExisting = self.updateExisting;
//調(diào)用MASConstraint的install方法
[constraint install];
}
[self.constraints removeAllObjects];
return constraints;
}
//MASViewConstraint(MASConstraint子類)的install方法
- (void)install {
...
...
MASLayoutConstraint *layoutConstraint
= [MASLayoutConstraint constraintWithItem:firstLayoutItem
attribute:firstLayoutAttribute
relatedBy:self.layoutRelation
toItem:secondLayoutItem
attribute:secondLayoutAttribute
multiplier:self.layoutMultiplier
constant:self.layoutConstant];
...
...
MASLayoutConstraint *existingConstraint = nil;
if (self.updateExisting) {
existingConstraint = [self layoutConstraintSimilarTo:layoutConstraint];
}
if (existingConstraint) {
// just update the constant
existingConstraint.constant = layoutConstraint.constant;
self.layoutConstraint = existingConstraint;
} else {
//調(diào)用系統(tǒng)方法添加約束
[self.installedView addConstraint:layoutConstraint];
self.layoutConstraint = layoutConstraint;
[firstLayoutItem.mas_installedConstraints addObject:self];
}
}
MASConstraint和其子類
- MASConstraint提供了基礎(chǔ)屬性(left,top,leftMargin...),且是創(chuàng)建鏈?zhǔn)秸Z法的必要要素
- MASCompositeConstraint內(nèi)有一個childConstraints的屬性,在布局的時候,會遍歷該數(shù)組,逐一進行install方法調(diào)用,make.edges,make.size返回的就是該類型
- MASViewConstraint是承載支持AutoLayout真正的對象,他創(chuàng)建了一個NSLayoutConstraint的必要屬性,并將其添加到對應(yīng)的view上;它的firstViewAttribute和secondViewAttribute屬性分別代表了對應(yīng)要設(shè)置約束兩個view的屬性
Masonry鏈?zhǔn)秸Z法實現(xiàn)原理
進入文件中可發(fā)現(xiàn)left,top..等maker屬性方法返回都是MASConstraint類型,而MASConstraint中也有這些相同的屬性方法,返回值依是MASCompositeConstraint對象,所有才能像
make.top.left.right...這樣使用Masonry,具體實現(xiàn)原理如下
1、MASConstraint的left方法:
- (MASConstraint *)left {
return [self addConstraintWithLayoutAttribute:NSLayoutAttributeLeft];
}
它會跳轉(zhuǎn)到MASViewConstraint的addConstraintWithLayout...方法
--------------------------------------------
2、MASViewConstraint的addConstraintWithLayout...方法
- (MASConstraint *)addConstraintWithLayoutAttribute:(NSLayoutAttribute)layoutAttribute {
return [self.delegate constraint:self addConstraintWithLayoutAttribute:layoutAttribute];
}
它會調(diào)用delegate的constraint...delegate就是MASConstraintMaker,來看看吧
--------------------------------------------
3、MASConstraintMaker的代理方法
- (MASConstraint *)constraint:(MASConstraint *)constraint addConstraintWithLayoutAttribute:(NSLayoutAttribute)layoutAttribute {
MASCompositeConstraint *compositeConstraint = [[MASCompositeConstraint alloc] initWithChildren:children];
[self constraint:constraint shouldBeReplacedWithConstraint:compositeConstraint];
return compositeConstraint;
}
創(chuàng)建的compositeConstraint布局時,就會調(diào)用children的install方法設(shè)置約束,從而達到通過點語法