masonry git地址:https://github.com/SnapKit/Masonry
本文主要會講到masonry英文文檔(見上面的git地址)中提及到的使用說明愚墓,以及個人使用過程中的一些經(jīng)驗,僅適用一些剛使用masonry的新手予权,大牛可以忽略浪册,當(dāng)然也可以進來指點扫腺。
一、常用的屬性與常量
1. MASViewAttribute 以對應(yīng)的系統(tǒng)類型
MASViewAttribute | NSLayoutAttribute |
---|---|
view.mas_left | NSLayoutAttributeLeft |
view.mas_right | NSLayoutAttributeRight |
view.mas_top | NSLayoutAttributeTop |
view.mas_bottom | NSLayoutAttributeBottom |
view.mas_leading | NSLayoutAttributeLeading |
view.mas_trailing | NSLayoutAttributeTrailing |
view.mas_width | NSLayoutAttributeWidth |
view.mas_height | NSLayoutAttributeHeight |
view.mas_centerX | NSLayoutAttributeCenterX |
view.mas_centerY | NSLayoutAttributeCenterY |
view.mas_baseline | NSLayoutAttributeBaseline |
2.UIView
先來一波最為常用的使用方法村象,大家可以看一下大致語法笆环,下面會細講使用
//.分別設(shè)置各個相對邊距(superview為view的父類視圖,下同)
make.left.mas_equalTo(superView.mas_left).mas_offset(10);
make.right.mas_equalTo(superView.mas_right).mas_offset(-10);
make.top.mas_equalTo(superView.mas_top).mas_offset(10);
make.bottom.mas_equalTo(superView.mas_bottom).offset(-10);
//直接連接使用left大于等于每個值
make.left.mas_greaterThanOrEqualTo(10);
//設(shè)置寬和高
make.width.mas_equalTo(60);
make.height.mas_equalTo(60);
//.設(shè)置center和款高比
make.center.mas_equalTo(superView);
make.width.mas_equalTo(superView).multipliedBy(1.00/3);
make.height.mas_equalTo(superView).multipliedBy(0.25);
//.關(guān)于約束優(yōu)先級,此處要注意約束沖突的問題厚者,統(tǒng)一約束優(yōu)先級大的生效
make.left.mas_equalTo(100);
make.left.mas_equalTo(view.superview.mas_left).offset(10);
make.left.mas_equalTo(20).priority(700);
make.left.mas_equalTo(40).priorityHigh();
make.left.mas_equalTo(60).priorityMedium();
make.left.mas_equalTo(80).priorityLow();
//.如果你想讓view的(x坐標)左邊大于等于label的左邊躁劣,以下兩個約束的寫法效果一樣
make.left.greaterThanOrEqualTo(label);
make.left.greaterThanOrEqualTo(label.mas_left);
注:約束的鏈式寫法中,不包含其他相對的view時库菲,默認為其superview账忘,即make.left.mas_equalTo(100);
等價于make.left.mas_equalTo(view.superview.mas_left).offset(10);
和make.left.mas_equalTo(view.superview).offset(10);
3. NSNumber
自動布局允許使用常量去設(shè)置寬或高,如果你想通過一個數(shù)字設(shè)置一個view的最小和最大的width,可以用equality blocks闪萄,如下:
//width >= 200 && width <= 400
make.width.greaterThanOrEqualTo(@200);
make.width.lessThanOrEqualTo(@400)
然而自動布局不允許對齊屬性的約束(如:left,right,centerY等)設(shè)置為常量值梧却,你可以使用NSNumber來設(shè)置相對于父類view這些約束屬性,如:
// creates view.left = view.superview.left + 10
make.left.lessThanOrEqualTo(@10)
如果你不想使用NSNumber來設(shè)置败去,也可以用如下結(jié)構(gòu)來創(chuàng)建你的約束放航,如:
make.top.mas_equalTo(42);
make.height.mas_equalTo(20);
make.size.mas_equalTo(CGSizeMake(50, 100));
make.edges.mas_equalTo(UIEdgeInsetsMake(10, 0, 10, 0));
make.left.mas_equalTo(view).mas_offset(UIEdgeInsetsMake(10, 0, 10, 0));
以上用法默認添加mas_前綴,如果你不想添加此前綴圆裕,但還想使用常量值設(shè)置約束广鳍,需要在導(dǎo)入Masonry頭文件前,設(shè)置宏定義MAS_SHORTHAND_GLOBALS吓妆,至于為什么赊时,去masonry代碼中搜索一下MAS_SHORTHAND_GLOBALS便知。
4. NSArray
用數(shù)組添加集中不同類的約束行拢,如:
make.height.equalTo(@[view1.mas_height, view2.mas_height]);
make.height.equalTo(@[view1, view2]);
make.left.equalTo(@[view1, @100, view3.right]);
二祖秒、約束的優(yōu)先級屬性
.priority允許你設(shè)置一個非常準確的的約束優(yōu)先級(0-1000)
.priorityHigh 相當(dāng)于系統(tǒng)的 UILayoutPriorityDefaultHigh
.priorityMedium 介于 high and low之間的優(yōu)先級
.priorityLow 相當(dāng)于系統(tǒng)的 UILayoutPriorityDefaultLow
注:默認通過mas_make添加的約束不設(shè)置優(yōu)先級時,默認都是最高(1000)
優(yōu)先級屬性可以放在約束鏈的末端使用舟奠,如:
make.left.greaterThanOrEqualTo(label.mas_left).with.priorityLow();
make.top.equalTo(label.mas_top).with.priority(600);
三竭缝、更加便利的約束方法
Masonry提供了一些便利的方法供我們同時創(chuàng)建多個不同的約束,他們被稱為MASCompositeConstraints沼瘫,如:
edges
// 使一個view的top, left, bottom, right 等于view2的
make.edges.equalTo(view2)抬纸;
//相對于superviewde上左下右邊距分別為5,10耿戚,15湿故,20
make.edges.equalTo(superview).insets(UIEdgeInsetsMake(5, 10, 15, 20))
size
// 使得寬度和高度大于等于 titleLabel
make.size.greaterThanOrEqualTo(titleLabel)
// 相對于superview寬度大100,高度小50
make.size.equalTo(superview).sizeOffset(CGSizeMake(100, -50))
center
//中心與button1對齊
make.center.equalTo(button1)
//水平方向中心相對向左偏移5膜蛔,豎直方向中心向下偏移10
make.center.equalTo(superview).centerOffset(CGPointMake(-5, 10))
你可以在約束鏈里添加相應(yīng)的view來增加代碼的可讀性:
// 除了top坛猪,所有的邊界與superview對齊
make.left.right.and.bottom.equalTo(superview);
make.top.equalTo(otherView);
四、關(guān)于如何修改約束
有時候皂股,你為了實現(xiàn)動畫或者移除替換一些約束時砚哆,你需要去修改一些已經(jīng)存在的約束,Masonry提供了一些不同的方法去更新約束屑墨,你也可以將多個約束存在數(shù)組里
1. References
你可以持有某個特定的約束躁锁,讓其成為成員變量或者屬性
//設(shè)置為公共或私接口
@property (nonatomic, strong) MASConstraint *topConstraint;
...
// 添加約束
[view1 mas_makeConstraints:^(MASConstraintMaker *make) {
self.topConstraint = make.top.equalTo(superview.mas_top).with.offset(padding.top);
make.left.equalTo(superview.mas_left).with.offset(padding.left);
}];
...
// 然后可以調(diào)用
//該約束移除
[self.topConstraint uninstall];
//重新設(shè)置value,最常用
self.topConstraint.mas_equalTo(20);
//該約束失效
[self.topConstraint deactivate];
//該約束生效
[self.topConstraint activate];
2. mas_updateConstraints
如果你只是想更新一下view對應(yīng)的約束,可以使用 mas_updateConstraints 方法代替 mas_makeConstraints方法
//這是蘋果推薦的添加或者更新約束的地方
// 在響應(yīng)setNeedsUpdateConstraints方法時卵史,這個方法會被調(diào)用多次
// 此方法會被UIKit內(nèi)部調(diào)用战转,或者在你觸發(fā)約束更新時調(diào)用
- (void)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);
}];
//調(diào)用super
[super updateConstraints];
}
3. mas_remakeConstraints
mas_updateConstraints只是去更新一些約束,然而有些時候修改一些約束值是沒用的,這時候mas_remakeConstraints就可以派上用場了
mas_remakeConstraints某些程度相似于mas_updateConstraints,但不同于mas_updateConstraints去更新約束值律胀,他會移除之前的view的所有約束闹蒜,然后再去添加約束
- (void)changeButtonPosition {
[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);
}
}];
五、在哪創(chuàng)建我的約束
貼一個官方說明的例子:
@implementation DIYCustomView
- (id)init {
self = [super init];
if (!self) return nil;
// --- Create your views here ---
self.button = [[UIButton alloc] init];
return self;
}
// tell UIKit that you are using AutoLayout
+ (BOOL)requiresConstraintBasedLayout {
return YES;
}
// this is Apple's recommended place for adding/updating constraints
- (void)updateConstraints {
// --- remake/update constraints here
[self.button remakeConstraints:^(MASConstraintMaker *make) {
make.width.equalTo(@(self.buttonSize.width));
make.height.equalTo(@(self.buttonSize.height));
}];
//according to apple super should be called at end of method
[super updateConstraints];
}
- (void)didTapButton:(UIButton *)button {
// --- Do your changes ie change variables that affect your layout etc ---
self.buttonSize = CGSize(200, 200);
// tell constraints they need updating
[self setNeedsUpdateConstraints];
}
六素标、Layout必備知識
AutoLayout關(guān)于更新的幾個方法的區(qū)別
setNeedsLayout:告知頁面需要更新险污,但是不會立刻開始更新致讥。執(zhí)行后會立刻調(diào)用layoutSubviews膀懈。
layoutIfNeeded:告知頁面布局立刻更新顿锰。所以一般都會和setNeedsLayout一起使用。如果希望立刻生成新的frame需要調(diào)用此方法启搂,利用這點一般布局動畫可以在更新布局后直接使用這個方法讓動畫生效硼控。
layoutSubviews:系統(tǒng)重寫布局
setNeedsUpdateConstraints:告知需要更新約束,但是不會立刻開始
updateConstraintsIfNeeded:告知立刻更新約束
updateConstraints:系統(tǒng)更新約束
七胳赌、使用tips
- 給view添加約束時牢撼,必須已經(jīng)添加到其superview上面
- 不需要設(shè)置
view.translatesAutoresizingMaskIntoConstraints = NO;
,masonry內(nèi)部已經(jīng)幫我設(shè)置過了 - 手寫布局時疑苫,合理使用約束熏版,盡量約束沖突問題
- 因為iOS中原點在左上角所以注意使用offset時注意right和bottom用負數(shù)
推薦兩個大牛寫的關(guān)于Masonry源碼解析的博客