Masonry是iOS開發中常見的視圖約束框架,但是有人對他的使用還是淺嘗輒止,接下來會提出幾點比較少見但是又十分便捷的使用技巧,
mas_greaterThanOrEqualTo
mas_greaterThanOrEqualTo顧名思義是不直接設定該約束,但是限制該約束不要超出邊界,比如我們想讓UILabel根據文本自適應長度(或高度)的話,就可以這么使用,
UILabel *textLb = [UILabel new];
textLb.font = [UIFont systemFontOfSize:30];
textLb.textColor = [UIColor redColor];
textLb.text = @"MrYu4";
[self.view addSubview:textLb];
[textLb mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.mas_equalTo(400);
make.left.mas_equalTo(10);
make.height.mas_equalTo(33);
make.width.mas_greaterThanOrEqualTo(0);
}];
效果圖如下,看得出來文本視圖的寬度跟文字長度正好適配,

除了與width/height搭配來約束寬/高之外,也可以與left/right約束在邊界,
另外mas_lessThanOrEqualTo則是相反的功能,但也是相同的用法,
priority
看這段代碼,猜一下textLb的高度會是比較高還是比較矮,
.......
[textLb mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.mas_equalTo(400);
make.left.mas_equalTo(10);
make.height.mas_equalTo(100).priorityHigh();
make.height.mas_equalTo(33).priorityMedium();
make.width.mas_greaterThanOrEqualTo(0);
}];

圖中可以看出priorityHigh()那句代碼優先級更高,在Masonry中兩個會沖突的約束可以用這三個優先級來手動設定哪個優先級更高
- (MASConstraint * (^)(void))priorityLow;
- (MASConstraint * (^)(void))priorityMedium;
- (MASConstraint * (^)(void))priorityHigh;
(三句話什么意思就不用我多說了吧)
當兩個會沖突的約束同時出現時,其實Masonry會根據自有邏輯來進行處理,但顯然作為開發我們肯定想這個邏輯規則牢牢把握在自己手上,比如下面這段代碼,width和right明顯出現了沖突,實際上這段代碼不互報錯,至于會顯示什么效果,可能會有很多人一時說不上來,
...
[textLb mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.mas_equalTo(400);
make.left.mas_equalTo(self.view.mas_right).offset(-70);
make.height.mas_equalTo(33);
make.right.mas_equalTo(-5);
make.width.mas_equalTo(100);
}];
這時候我們要做的就是添加上優先級(優先級落后的也要加上),這樣子代碼就會順著我們的想法去走,比如我要求的是寧愿超出螢屏也要寬度保證為100,就可以這么寫,
...
make.right.mas_equalTo(-5).priorityMedium();
make.width.mas_equalTo(100).priorityHigh();

父視圖大小適配子視圖的大小
有時候一個view的大小需要其子視圖來確認(尤其是其子視圖的大小還可能需要等服務器回傳資料之后才能確認其大小),這個時候我們其實不需要學習到什么新的方法,只需要在設定父視圖時添加對子視圖的依賴即可,
//此處是父視圖
UIView *blueView = [UIView new];
blueView.backgroundColor = [UIColor blueColor];
//下面是兩個子視圖
UILabel *textLb = [UILabel new];
textLb.font = [UIFont systemFontOfSize:30];
textLb.textColor = [UIColor redColor];
[blueView addSubview:textLb];
[textLb mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.mas_equalTo(0);
make.left.mas_equalTo(20);//表示其在父視圖左邊距20處,相對來講,父視圖至少左側有20長度的寬度了
make.height.mas_equalTo(33);
make.width.mas_greaterThanOrEqualTo(0);
}];
UILabel *textLb2 = [UILabel new];
textLb2.font = [UIFont systemFontOfSize:30];
textLb2.textColor = [UIColor redColor];
[blueView addSubview:textLb2];
[textLb2 mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.mas_equalTo(textLb);
make.left.mas_equalTo(textLb.mas_right);
make.height.mas_equalTo(33);
make.width.mas_greaterThanOrEqualTo(0);
}];
[self.view addSubview:blueView];
[blueView mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.mas_equalTo(400);
make.left.mas_equalTo(12);
make.right.mas_equalTo(textLb2);//關鍵點
make.height.mas_equalTo(70);
}];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC * 2), dispatch_get_main_queue(), ^{
//模擬服務器回傳資料
textLb.text = @"MrYu4";
textLb2.text = @"服務器回傳文字";
});

還有的朋友把子視圖寫在父視圖的類里面,處理方法也是同理的,只需要注意的時候不要把寫好的約束給覆寫甚至移除掉就好了,
多個view并排(列)等寬/距離的實作
要實作這個功能主要仰仗Masonry中NSArray+MASAdditions.h,核心思路就是將所有的view放入陣列中,并將這個陣列合并成一個個體來思考,
1、實作相同約束
NSArray+MASAdditions.h實作了和UIView+MASAdditions.h同名的方法,當我們想讓陣列里的view各個添加一樣的約束時,直接對陣列添加就好,
//@interface NSArray (MASAdditions)
- (NSArray *)mas_makeConstraints:(void (NS_NOESCAPE ^)(MASConstraintMaker *make))block;
- (NSArray *)mas_updateConstraints:(void (NS_NOESCAPE ^)(MASConstraintMaker *make))block;
- (NSArray *)mas_remakeConstraints:(void (NS_NOESCAPE ^)(MASConstraintMaker *make))block;
也許大聰明還在用
for回圈來對每個view添加相同約束,其實上面的方法就是這些大聰明的做法的封裝,- (NSArray *)mas_makeConstraints:(void(^)(MASConstraintMaker *make))block { NSMutableArray *constraints = [NSMutableArray array]; for (MAS_VIEW *view in self) { NSAssert([view isKindOfClass:[MAS_VIEW class]], @"All objects in the array must be views"); //注意這個[view mas_makeConstraints:block],還有估計有人還沒注意到兩邊的同名方法其實是有回傳值的(回傳約束陣列) [constraints addObjectsFromArray:[view mas_makeConstraints:block]]; } return constraints; }
2、平均排列
NSArray+MASAdditions.h還有兩個未提及的方法,此刻可以派上用場了,
/**
* distribute with fixed spacing
*
* @param axisType which axis to distribute items along
* @param fixedSpacing 每個item之間的距離
* @param leadSpacing the spacing before the first item and the container
* @param tailSpacing the spacing after the last item and the container
*/
- (void)mas_distributeViewsAlongAxis:(MASAxisType)axisType withFixedSpacing:(CGFloat)fixedSpacing leadSpacing:(CGFloat)leadSpacing tailSpacing:(CGFloat)tailSpacing;
/**
* distribute with fixed item size
*
* @param axisType which axis to distribute items along
* @param fixedItemLength 每個item的長度
* @param leadSpacing the spacing before the first item and the container
* @param tailSpacing the spacing after the last item and the container
*/
- (void)mas_distributeViewsAlongAxis:(MASAxisType)axisType withFixedItemLength:(CGFloat)fixedItemLength leadSpacing:(CGFloat)leadSpacing tailSpacing:(CGFloat)tailSpacing;
兩個方法只有一個引數不一樣,也體現了二者方法使用場景的不同:
- item距離固定,item寬度根據父視圖空間適應
- item寬度固定,item間距離根據父視圖空間適應
3、代碼
目標:藍色view作為父視圖,有紅黃綠各三個view距離固定為10,等寬顯示,
NSArray <UIView *>*views = @[redView,yellowView,greenView];
[views mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.bottom.mas_equalTo(0);
}];
[views mas_distributeViewsAlongAxis:MASAxisTypeHorizontal
withFixedSpacing:10
leadSpacing:0
tailSpacing:0];

轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/433199.html
標籤:iOS
上一篇:AndroidManifest.xml檔案報Activity supporting ACTION_VIEW is not set as BROWSABLE
