亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

使用Masonry搭建特殊布局時與xib的對比

2019-11-14 18:07:49
字體:
來源:轉載
供稿:網友

之前只有比較淺的接觸過Masonry。項目中大多數的布局還是用xib中的AutoLayout與手碼的frame計算相結合,相信也會有很多項目和我一樣是這兩種布局的組合。其實xib各方面用的感覺都挺好,以前是性能問題,沖突問題飽受人詬病,但隨著蘋果的更新換代這些問題也逐漸趨向最小化。 我們團隊整改的主要原因是為了更細粒度的組件化。因為將一塊代碼復用到另一個頁面遠比從xib中拖幾個控件到別的頁面來的要快,并且使用Masonry寫出來的代碼在控件間關系上非常清晰便于理解。

普通的布局就略過不說了,這里搭建一些較為特殊的布局。

如果你不是在董鉑然博客園看到本文請點擊查看原文。

1.下方有三個UIView或UIButton,要隨時隨著屏幕寬度的變化(橫屏豎屏)始終保持等寬等高。

 

上面的右圖是xib下搭建,使用常規的Masonry語法完成布局的代碼是這樣的

    [redView mas_makeConstraints:^(MASConstraintMaker *make) {        make.left.equalTo(self.view.mas_left).with.offset(0);        make.bottom.equalTo(self.view.mas_bottom).with.offset(0);        make.height.equalTo(@100);    }];        [blueView mas_makeConstraints:^(MASConstraintMaker *make) {        make.left.equalTo(redView.mas_right).with.offset(0);        make.bottom.equalTo(self.view.mas_bottom).with.offset(0);        make.width.equalTo(redView.mas_width).with.offset(0);        make.height.equalTo(redView.mas_height).with.offset(0);    }];        [greenView mas_makeConstraints:^(MASConstraintMaker *make) {        make.left.equalTo(blueView.mas_right).with.offset(0);        make.bottom.equalTo(self.view.mas_bottom).with.offset(0);        make.right.equalTo(self.view.mas_right).with.offset(0);        make.width.equalTo(blueView.mas_width).with.offset(0);        make.height.equalTo(blueView.mas_height).with.offset(0);    }];

代碼中可以看到具體的邏輯還是特別清晰的??梢郧宄亓私飧鱾€控件間的關系,基本上每一行代表著xib中的一根約束。

并且Masonry支持了一些省略和簡寫:

如果是兩個控件的同一個位置(約束)之間的聯系,括號中可以只寫以來的控件約束可以省略;

如果約束依賴的是同一個控件,那可以用and將兩個約束連在一行寫;

如果偏移量offset是0,后面的with.offset(0)可以省略;

將上面的代碼最簡可以寫成如下

    [redView mas_makeConstraints:^(MASConstraintMaker *make) {        make.left.and.bottom.equalTo(self.view);        make.height.equalTo(@100);    }];        [blueView mas_makeConstraints:^(MASConstraintMaker *make) {        make.bottom.and.width.and.height.equalTo(redView);        make.left.equalTo(redView.mas_right);    }];        [greenView mas_makeConstraints:^(MASConstraintMaker *make) {        make.bottom.and.width.and.height.equalTo(blueView);        make.right.equalTo(self.view);        make.left.equalTo(blueView.mas_right);    }];

注:對于這種幾個模塊功能相似位置相近的,建議多包一層父控件,便于整個組件的操作與抽離,并且可以從宏觀的角度看項目結構更加清晰。 

 

2.實現相互依賴的自動布局,背景View的高度由自己子控件的Label能拉多長決定。

簡單的描述就是,label的左邊和頂部是依賴父控件grayView的。但是父控件grayView的底部是依賴子控件Label的。

上面右圖是IB頁面搭建的AutoLayout,但是按照xib的搭建的思路寫出的代碼是有問題的。

    [grayView mas_makeConstraints:^(MASConstraintMaker *make) {        make.left.and.top.equalTo(self.view).with.offset(50);        make.width.equalTo(@200);        make.bottom.equalTo(contentLbl).with.offset(10);    }];        [contentLbl mas_makeConstraints:^(MASConstraintMaker *make) {        make.left.and.top.equalTo(grayView).with.offset(10);        make.right.equalTo(grayView).with.offset(-10);    }];

 上面的代碼會導致崩潰,原因就是上面的第4行依賴的contentLbl的約束還沒有搭建所以導致崩潰。在xib中會出現紅色箭頭的情況,就是約束錯誤,在將約束調整正確后紅色箭頭會變成黃色箭頭,就是約束正確。 但是使用Masonry與xib不同,xib出現錯誤可以容忍你改正,Masonry只要出現錯誤就會馬上崩潰。 因此對于這種相互依賴的約束,下面的還沒建立就要約束他看似無法完成,實際的解決方案就是用子控件反過來依賴他也是可以的。 也就是說,你想讓父控件依賴子控件比他多10像素,和設置子控件依賴父控件比他少10像素是一個等價的概念,可以相互轉化。如果你是細心的網友,你會發現在xib中你雖然設置的是父控件依賴子控件,但實際的約束還是放在子控件里的。

修改后的代碼如下:

    [grayView mas_makeConstraints:^(MASConstraintMaker *make) {        make.left.and.top.equalTo(self.view).with.offset(50);        make.width.equalTo(@200);    }];        [contentLbl mas_makeConstraints:^(MASConstraintMaker *make) {        make.left.and.top.equalTo(grayView).with.offset(10);        make.right.equalTo(grayView).with.offset(-10);        make.bottom.equalTo(grayView).with.offset(-10);    }];

 

3.設置百分比的約束,即一個約束是另一個約束百分之多少。

這種約束一般適用于width和height。 對于屏幕的適配很有用,等于把以前算frame的思想加到了autoLayout里。

    [grayView mas_makeConstraints:^(MASConstraintMaker *make) {        make.left.and.top.equalTo(self.view).with.offset(50);//        make.width.equalTo(@200);        make.width.equalTo(self.view).multipliedBy(0.5).offset(0);    }];        [contentLbl mas_makeConstraints:^(MASConstraintMaker *make) {        make.left.and.top.equalTo(grayView).with.offset(10);        make.right.equalTo(grayView).with.offset(-10);        make.bottom.equalTo(grayView).with.offset(-10);    }];

和原生的約束一樣,設置向量系數(比例)之后也可以再設置一個偏移量。

 

4.設置約束的更新

當前的自動布局第三方庫有多種,Masonry相比來說也算是重量級的了。Masonry相比其他自動布局的庫最大的優點是在于約束的更新做的很好。

假設現在的約束是上面第2條時的約束,現在設置按鈕點擊更新約束代碼如下

- (IBAction)btnclick:(id)sender {    [self.grayView mas_updateConstraints:^(MASConstraintMaker *make) {        make.width.equalTo(@300);    }];    [UIView animateWithDuration:3.0 animations:^{        [self.grayView layoutIfNeeded];    }];}

如果給約束的變化設置約束,需要用UIView動畫的block將 layoutIfNeed包裹住。而不是直接將約束更新包裹住。

更新約束要注意mas_updateConstraints 和 mas_remakeConstraints 有本質區別。 前者update是保留之前的約束再添加你本次新增的約束。如果出現了相同的設置約束的方法,僅僅是值不同,則會直接替換掉原來的約束。  后者remake是直接把原來的全部干掉,然后添加本次設置的約束。

所以update要注意的是不要用新的方法添加了約束會與之前的約束相沖突。而remake需要注意的是你在remake里面寫的約束必須是一個完整的約束,因為之前的約束全清空了。

如果沒有完全弄清兩個方法的區別則可能會寫出以下代碼,這是錯誤的

- (IBAction)btnclick:(id)sender {    [self.grayView mas_updateConstraints:^(MASConstraintMaker *make) {        make.left.and.top.equalTo(self.view).with.offset(10);        make.width.equalTo(self.view).multipliedBy(0.5);    }];        [UIView animateWithDuration:3.0 animations:^{        [self.grayView layoutIfNeeded];    }];}

因為原來的make.width.equalTo(@200); 和本次的 make.width.equalTo(self.view).multipliedBy(0.5); 雖然都是設置width但是設置方法不同,所以會會新舊都保留導致沖突報錯。

如果你不是在董鉑然博客園看到本文請點擊查看原文。

 

5.設置優先級和Label抗壓縮

有的時候Label的寬度或是內部字體發生變化的時候,可能會出現XX... 這種情況,這是因為Label被壓縮了。Masonry有抗壓縮的設置,并且這個設置和Masonry的優先級PRiority息息相關。iOS9字體的變化導致很多Label出現... ,如果當初使用Masonry來設置布局并且設置了抗壓縮,那應該就可以完全避免此問題。

設置一個View,里面有一個子控件Label。

    [blackView mas_makeConstraints:^(MASConstraintMaker *make) {        make.left.equalTo(self.view).with.offset(50);        make.top.equalTo(self.view).with.offset(300);        make.size.mas_equalTo(CGSizeMake(200, 50));    }];        [contentLbl2 mas_makeConstraints:^(MASConstraintMaker *make) {        make.left.and.top.equalTo(blackView).with.offset(10);        make.right.equalTo(blackView).with.offset(-50);        make.height.equalTo(@30);    }];

上面的第一塊代碼就是搭建一個普通的父控件,可以無視。下面一塊是Label的約束

如果這么設置,右邊要比父控件少50,所以Label的文字顯示不下,會被積壓。

 

但是如果加入一個約束:“width最少也大于200”,并且給這個約束設置優先級比 “右邊要比父控件少50” 的優先級高,代碼如下

    [contentLbl2 mas_makeConstraints:^(MASConstraintMaker *make) {        make.left.and.top.equalTo(blackView).with.offset(10);        make.width.greaterThanOrEqualTo(@200).priority(900);        make.right.equalTo(blackView).with.offset(-50).priority(800);        make.height.equalTo(@30);    }];

第3行的優先級大于第4行的優先級 所以執行第3行,Label并沒有被擠壓。

 

抗壓縮還有另一種設置方法 

    [contentLbl2 mas_makeConstraints:^(MASConstraintMaker *make) {        make.left.and.top.equalTo(blackView).with.offset(10);        make.right.equalTo(blackView).with.offset(-50).priority(990);        make.height.equalTo(@30);    }];        [contentLbl2 setContentCompressionResistancePriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisHorizontal];

設置“右邊要比父控件少50” 的優先級為1000以下, 然后在下面再寫上一行水平方向抗壓縮的代碼。 這里要注意上面的“右邊比父控件少50”優先級不能不寫,因為Masonry這種類型的代碼默認優先級都是1000,而下面UILayoutPriorityRequired的優先級也是1000,那么下面的代碼就不起效果了。

 

其實還有更簡單的設置方法,不用寫水平方向抗壓縮,只需要將上面約束后面的優先級改到750以下

    [contentLbl2 mas_makeConstraints:^(MASConstraintMaker *make) {        make.left.and.top.equalTo(blackView).with.offset(10);        make.right.equalTo(blackView).with.offset(-50).priority(749);        make.height.equalTo(@30);    }];

因為優先級750對應的優先級枚舉是UILayoutPriorityDefaultHigh,可以理解成Masonry本身就有一種抗壓縮的保護,優先級是750。

    [contentLbl2 setContentCompressionResistancePriority:UILayoutPriorityDefaultHigh forAxis:UILayoutConstraintAxisHorizontal];

這行代碼應該是所有label默認存在的。

所以以后如果想讓Label抗壓縮,直接把優先級設置到750以下就OK了。

 

總結:

1.Masonry的方法并不多,鏈式方法,每一個點語法都是返回一個約束對象,一個個特定的約束是這個對象的屬性。

2.Masonry不同于xib搭建約束出現紅色還能調整,前者一出現問題直接崩潰,將問題卡在開發階段。

3.Masonry建立約束前必須將父子關系搭建好,并且不能對還沒有設置約束的控件添加依賴。

4.更新約束要弄清remake和update的區別。

未經授權不得轉載


上一篇:iBeacon開發筆記

下一篇:IOS之導航控制器

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
久久久亚洲国产天美传媒修理工| 亚洲自拍偷拍色图| 亚洲第一男人天堂| 久久亚洲精品一区二区| 在线观看成人黄色| 青青草原成人在线视频| 国产成人精品一区| 国产精品精品国产| 久久久久国产精品免费| 国产成人精品免高潮费视频| 国内精品一区二区三区| 亚洲男人天堂九九视频| 中文字幕综合一区| 91精品国产91久久久| 日韩久久免费电影| 欧美片一区二区三区| 欧美中文在线免费| 欧美激情高清视频| 麻豆一区二区在线观看| 精品久久久久久亚洲精品| 日韩成人网免费视频| 日韩中文理论片| 在线播放国产一区二区三区| 欧美丰满少妇xxxxx做受| 成人在线中文字幕| 美女扒开尿口让男人操亚洲视频网站| 亚洲国产成人精品久久| 成人在线视频网站| 日韩精品在线观| 成人乱人伦精品视频在线观看| 国产日韩av在线播放| 国内精品久久久久久久| 一区二区在线视频| 亚洲精品日韩av| 国产精品丝袜久久久久久高清| 久久精品视频中文字幕| 久久琪琪电影院| 成人久久18免费网站图片| 国产精品精品一区二区三区午夜版| 在线视频一区二区| 国模精品视频一区二区| xxx欧美精品| 色综合91久久精品中文字幕| 91超碰caoporn97人人| 欧美精品在线视频观看| 日韩最新免费不卡| 国产成人久久久| 色偷偷亚洲男人天堂| 国产在线视频91| 精品视频偷偷看在线观看| 欧美性xxxxxxx| 97在线免费观看| 日韩欧美在线视频日韩欧美在线视频| 亚洲在线一区二区| 亚洲性69xxxbbb| 国产欧美日韩免费看aⅴ视频| 一区二区在线视频| 亚洲精品短视频| 亚洲视频精品在线| 国产精品久久久久久av| 一区二区三区日韩在线| 亚洲韩国日本中文字幕| 国产亚洲一级高清| 亚洲aa中文字幕| 色综合久久天天综线观看| 欧美性xxxxhd| 欧美日本高清一区| 亚洲免费电影一区| 亚洲精品一二区| 日韩欧美在线免费观看| 成人久久久久久久| 欧美日韩亚洲网| 日韩在线观看免费av| 久久久久中文字幕2018| 在线观看日韩www视频免费| 日韩精品极品视频免费观看| 国产91亚洲精品| 日本不卡高字幕在线2019| 日本一区二三区好的精华液| 国产精品久久久久久久久粉嫩av| 狠狠色香婷婷久久亚洲精品| 久久福利视频网| 欧美性受xxx| 91久久精品久久国产性色也91| 日韩欧美中文字幕在线播放| 亚洲一区二区在线播放| 久久久久久久久久久久久久久久久久av| 亚洲国产成人爱av在线播放| 日韩在线免费高清视频| 欧美性xxxxx| 亚洲人高潮女人毛茸茸| 91香蕉嫩草影院入口| 尤物tv国产一区| 亚洲综合在线播放| 国产亚洲视频中文字幕视频| 日韩最新av在线| 亚洲福利在线视频| 成人国产精品免费视频| 久久手机精品视频| 91日本在线视频| www.欧美三级电影.com| 成人h视频在线观看播放| 久久精品青青大伊人av| 色悠悠国产精品| 国产日韩精品综合网站| 久久手机精品视频| 亚洲女同精品视频| 91免费精品视频| 一区二区三区精品99久久| 国产欧美一区二区三区四区| 成人信息集中地欧美| 日韩大片免费观看视频播放| 亚洲国产精品久久久久| 日韩在线视频中文字幕| 日韩精品在线视频观看| 欧美大片网站在线观看| 亚洲欧美激情视频| 亚洲精品国产拍免费91在线| 亚洲丝袜av一区| 国产97免费视| 亚洲剧情一区二区| 欧美特黄级在线| 亚洲色图35p| 久久久久久尹人网香蕉| 国产亚洲精品91在线| 久久综合久久美利坚合众国| 欧洲亚洲免费视频| 91在线免费观看网站| 国产一区二区三区在线观看网站| 日韩激情视频在线| 午夜免费在线观看精品视频| 久青草国产97香蕉在线视频| 亚洲性av在线| 中文字幕日韩免费视频| 欧美激情视频播放| 欧美亚洲成人免费| 久久精品国产69国产精品亚洲| 岛国av午夜精品| 国产精品尤物福利片在线观看| 欧美国产亚洲视频| 狠狠色噜噜狠狠狠狠97| 亚洲国产欧美一区二区三区久久| 久久国产精品久久久| 在线播放精品一区二区三区| 91香蕉嫩草影院入口| 亚洲一区二区少妇| 国产在线精品成人一区二区三区| 九九九久久久久久| 懂色aⅴ精品一区二区三区蜜月| 亚洲色图第一页| 91精品久久久久久久久不口人| 国产亚洲欧洲在线| 在线看欧美日韩| 精品亚洲一区二区三区| 成人国产在线视频| 亚洲电影免费观看| 超碰91人人草人人干| 亚洲成人a级网| 国产精品一区二区三区免费视频| 日韩日本欧美亚洲| 亚洲va久久久噜噜噜| 国产香蕉一区二区三区在线视频| 国产精品久久久久久久久| 日本在线精品视频|