Masonry是一個輕量級的封裝了Autolayout框架
https://github.com/Masonry/Masonry
github頁面上給出了使用Masonry和Autolayout實現同樣效果代碼量的對比
當然了你如果學習了VFL,代碼量也不會很多
平常我們使用Autolayout要設置view.translatesAutoresizingMaskIntoConstraints = NO;
Masonry會自動幫我們調用這行代碼
結合官方的實例看幾個小時差不多就能使用Masonry了,
UIEdgeInsets padding = UIEdgeInsetsMake(10, 10, 10, 10);
[view1 mas_makeConstraints:^(MASConstraintMaker *make) { make.top.equalTo(superview.mas_top).with.offset(padding.top); //with is an optional semantic filler make.left.equalTo(superview.mas_left).with.offset(padding.left); make.bottom.equalTo(superview.mas_bottom).with.offset(-padding.bottom); make.right.equalTo(superview.mas_right).with.offset(-padding.right); }];
讓一個在父視圖上上下左右各縮進10個長度(請自動腦補如果使用Autolayout的代碼量)
下面是效果圖

或者你可以用一行代碼搞定上面的效果圖
[view1 mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(superview).with.insets(padding);
}];
腫么樣,給力吧
除了可以使用make.edges還可以使用make.size等,直接設置size約束
Masonry還會自動識別你要設置的屬性(上,下,左,右),下面兩行代碼的效果等價
make.left.greaterThanOrEqualTo(label);
make.left.greaterThanOrEqualTo(label.mas_left);
下面是寬度約束的代碼
make.width.greaterThanOrEqualTo(@200); make.width.lessThanOrEqualTo(@400)
然而,Autolayout不允許對齊元素(left ,centerX)等寫成常量 ,所以如果你寫成下面那句代碼
make.left.lessThanOrEqualTo(@10)
Masonry會自動幫你轉換為下面的約束式(關聯superView)
view.left = view.superview.left + 10
你出了可以使用NSNumber,還可以使用基本類型量和結構體(最下面那句代碼是多次設置)
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));
此外你還可以添加NSArray(一組)約束
make.height.equalTo(@[view1.mas_height, view2.mas_height]); make.height.equalTo(@[view1, view2]); make.left.equalTo(@[view1, @100, view3.right]);
還可以一次添加多個約束,使用鏈式語句或者結構體
Masonry also gives you a few convenience methods which create multiple constraints at the same time. These are called MASCompositeConstraints edges // make top, left, bottom, right equal view2 make.edges.equalTo(view2); // make top = superview.top + 5, left = superview.left + 10, // bottom = superview.bottom - 15, right = superview.right - 20 make.edges.equalTo(superview).insets(UIEdgeInsetsMake(5, 10, 15, 20)) size // make width and height greater than or equal to titleLabel make.size.greaterThanOrEqualTo(titleLabel) // make width = superview.width + 100, height = superview.height - 50 make.size.equalTo(superview).sizeOffset(CGSizeMake(100, -50)) center // make centerX and centerY = button1 make.center.equalTo(button1) // make centerX = superview.centerX - 5, centerY = superview.centerY + 10 make.center.equalTo(superview).centerOffset(CGPointMake(-5, 10)) You can chain view attributes for increased readability: // All edges but the top should equal those of the superview make.left.right.and.bottom.equalTo(superview); make.top.equalTo(otherView);
你還可以定義約束的優先級,當約束出現沖突的時候,優先級高的約束覆蓋優先級低的約束(下面的代碼是添加優先級)
make.left.greaterThanOrEqualTo(label.mas_left).with.priorityLow(); make.top.equalTo(label.mas_top).with.priority(600);
有時候我們需要去掉某些約束,或者修改某些約束(動畫等),這個時候腫么辦呢?
// in public/private interface @property (nonatomic, strong) MASConstraint *topConstraint; ... // when making constraints [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); }]; ... // then later you can call [self.topConstraint uninstall];
使用一個引用,在不需要的時候,調用uninstall就可以去掉約束了
如果你后續需要改變約束(添加動畫等),你可以調用另外一個創建約束的方法,並把約束需要的值,寫成變量(蘋果建議添加個更新約束寫在updateConstraints方法中)
// this is Apple's recommended place for adding/updating constraints // this method can get called multiple times in response to setNeedsUpdateConstraints // which can be called by UIKit internally or in your code if you need to trigger an update to your constraints - (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); }]; //according to apple super should be called at end of method [super updateConstraints]; }
有時候我們為了改變約束,需要有變量來引用約束,這個時候如果需要改變的約束非常多,那么這將是一個非常蛋疼的代碼量
所以Masonry提供了一個重建約束的方法,使用這個方法,建立約束之前會把之前的約束全部清除掉,然后重新添加,這樣我們只需要添加執行邏輯代碼就行了(判斷等)
如下
mas_updateConstraints is useful for updating a set of constraints, but doing anything beyond updating constant values can get exhausting. That's where mas_remakeConstraints comes in. mas_remakeConstraints is similar to mas_updateConstraints, but instead of updating constant values, it will remove all of its contraints before installing them again. This lets you provide different constraints without having to keep around references to ones which you want to remove. - (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); } }]; }
約束出現問題的時候控制台打印的信息過於籠統,不容易讓人發現問題,為此Masonry,添加了分類,重寫了約束的description方法
從而可以給出更詳細的提示信息
Masonry adds a category to NSLayoutConstraint which overrides the default implementation of - (NSString *)description. Now you can give meaningful names to views and constraints, and also easily pick out the constraints created by Masonry.
Masonry還給出了snippets
Copy the included code snippets to ~/Library/Developer/Xcode/UserData/CodeSnippets to write your masonry blocks at lightning speed! mas_make -> [<view> mas_makeConstraints:^(MASConstraintMaker *make){<code>}]; mas_update -> [<view> mas_updateConstraints:^(MASConstraintMaker *make){<code>}]; mas_remake -> [<view> mas_remakeConstraints:^(MASConstraintMaker *make){<code>}];
