Masonry
基本原理
-
基于iOS系统的
Autolayout
,是对系统autolayout
的封装。 -
根据
item1.attribute1 = multiplier * item2.attribute1 + offset
构建一个NSLayoutConstraint
-
将
NSLayoutConstraint
添加到视图中。有些需要加入到视图自身上,有些需要加入到两个视图的最近父节点上面。找最近父节点,这其实是一个经典的算法题,可以有各种花哨的算法,而Masnory
是通过双层循环,主要视图的层次结构不会嵌套很深,所以这样也不会太影响性能。
源码解析
- 通过
view category
, 提供了设置布局的三个方法:-
- (NSArray *)mas_makeConstraints:(void(^)(MASConstraintMaker *make))block;
-
- (NSArray *)mas_updateConstraints:(void(^)(MASConstraintMaker *make))block;
-
- (NSArray *)mas_remakeConstraints:(void(^)(MASConstraintMaker *make))block;
-
以及@property (nonatomic, strong, readonly) MASViewAttribute *mas_left;
等布局属性。
mas_makeConstraints
实现:
- (NSArray *)mas_makeConstraints:(void(^)(MASConstraintMaker *))block {
self.translatesAutoresizingMaskIntoConstraints = NO;
MASConstraintMaker *constraintMaker = [[MASConstraintMaker alloc] initWithView:self];
block(constraintMaker);
return [constraintMaker install];
}
方法内部会先创建一个MASConstraintMaker
的maker
,并将此maker
传入block
执行,生成一堆layoutConstraints
,最后在将layoutConstraints
添加到对应的视图中。
mas_updateConstraints
、mas_remakeConstraints
与mas_makeConstraints
类似,只是分别会设置maker
的updateExisting
、removeExisting
属性。有啥用???
mas_left
等布局属性:
- (MASViewAttribute *)mas_left {
return [[MASViewAttribute alloc] initWithView:self layoutAttribute:NSLayoutAttributeLeft];
}
生成一个对应MASViewAttribute
对象。MASViewAttribute
这个类其实就是view
和属性的一个包装而已。
-
MASConstraintMaker
分析:
提供了@property (nonatomic, strong, readonly) MASConstraint *left;
等单个layoutConstraint
、@property (nonatomic, strong, readonly) MASConstraint *size;
等复合布局约束、- (MASConstraint * (^)(dispatch_block_t))group;
及上文中提及的install
方法、updateExisting
属性、removeExisting
属性。
left
属性
- (MASConstraint *)left {
return [self addConstraintWithLayoutAttribute:NSLayoutAttributeLeft];
}
调用
- (MASConstraint *)addConstraintWithLayoutAttribute:(NSLayoutAttribute)layoutAttribute {
return [self constraint:nil addConstraintWithLayoutAttribute:layoutAttribute];
}
size
属性
- (MASConstraint *)addConstraintWithLayoutAttribute:(NSLayoutAttribute)layoutAttribute {
return [self constraint:nil addConstraintWithLayoutAttribute:layoutAttribute];
}