Masonry
使用
- 關(guān)鍵方法:
- (NSArray *)mas_makeConstraints:(void(^)(MASConstraintMaker *make))block;
- 約束方法除了equalTo,還有l(wèi)essThanOrEqualTo和greaterThanOrEqualTo
- 當(dāng)已有約束需要更新時(shí)調(diào)用
mas_updateConstraints
方法mas_remakeConstraints
方法會(huì)先清除當(dāng)前所有約束再布置- Masonry的五大參數(shù):
Attribute(屬性) ,Relation(關(guān)系),Multiplier(乘),Constant(大小),Priority(優(yōu)先級(jí))
//一個(gè)系統(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);
// 等價(jià)于
// make.edges.equalTo(superView).with.insets(UIEdgeInsetsMake(10, 10, 10, 10));
// 會(huì)自動(dòng)調(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對(duì)象,然后傳遞到block執(zhí)行,完成后調(diào)用maker的install方法來(lái)確保約束被添加到視圖中
//設(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對(duì)象中的所有約束
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子類(lèi))的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和其子類(lèi)
- MASConstraint提供了基礎(chǔ)屬性(left,top,leftMargin...),且是創(chuàng)建鏈?zhǔn)秸Z(yǔ)法的必要要素
- MASCompositeConstraint內(nèi)有一個(gè)childConstraints的屬性,在布局的時(shí)候,會(huì)遍歷該數(shù)組,逐一進(jìn)行install方法調(diào)用,make.edges,make.size返回的就是該類(lèi)型
- MASViewConstraint是承載支持AutoLayout真正的對(duì)象,他創(chuàng)建了一個(gè)NSLayoutConstraint的必要屬性,并將其添加到對(duì)應(yīng)的view上;它的firstViewAttribute和secondViewAttribute屬性分別代表了對(duì)應(yīng)要設(shè)置約束兩個(gè)view的屬性
Masonry鏈?zhǔn)秸Z(yǔ)法實(shí)現(xiàn)原理
進(jìn)入文件中可發(fā)現(xiàn)left,top..等maker屬性方法返回都是MASConstraint類(lèi)型,而MASConstraint中也有這些相同的屬性方法,返回值依是MASCompositeConstraint對(duì)象,所有才能像
make.top.left.right...
這樣使用Masonry,具體實(shí)現(xiàn)原理如下
1利诺、MASConstraint的left方法:
- (MASConstraint *)left {
return [self addConstraintWithLayoutAttribute:NSLayoutAttributeLeft];
}
它會(huì)跳轉(zhuǎn)到MASViewConstraint的addConstraintWithLayout...方法
--------------------------------------------
2糙箍、MASViewConstraint的addConstraintWithLayout...方法
- (MASConstraint *)addConstraintWithLayoutAttribute:(NSLayoutAttribute)layoutAttribute {
return [self.delegate constraint:self addConstraintWithLayoutAttribute:layoutAttribute];
}
它會(huì)調(diào)用delegate的constraint...delegate就是MASConstraintMaker销凑,來(lái)看看吧
--------------------------------------------
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布局時(shí),就會(huì)調(diào)用children的install方法設(shè)置約束,從而達(dá)到通過(guò)點(diǎn)語(yǔ)法