国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 學(xué)院 > 開(kāi)發(fā)設(shè)計(jì) > 正文

使用Masonry搭建特殊布局時(shí)與xib的對(duì)比

2019-11-14 18:07:49
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

之前只有比較淺的接觸過(guò)Masonry。項(xiàng)目中大多數(shù)的布局還是用xib中的AutoLayout與手碼的frame計(jì)算相結(jié)合,相信也會(huì)有很多項(xiàng)目和我一樣是這兩種布局的組合。其實(shí)xib各方面用的感覺(jué)都挺好,以前是性能問(wèn)題,沖突問(wèn)題飽受人詬病,但隨著蘋(píng)果的更新?lián)Q代這些問(wèn)題也逐漸趨向最小化。 我們團(tuán)隊(duì)整改的主要原因是為了更細(xì)粒度的組件化。因?yàn)閷⒁粔K代碼復(fù)用到另一個(gè)頁(yè)面遠(yuǎn)比從xib中拖幾個(gè)控件到別的頁(yè)面來(lái)的要快,并且使用Masonry寫(xiě)出來(lái)的代碼在控件間關(guān)系上非常清晰便于理解。

普通的布局就略過(guò)不說(shuō)了,這里搭建一些較為特殊的布局。

如果你不是在董鉑然博客園看到本文請(qǐng)點(diǎn)擊查看原文

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

 

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

    [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);    }];

代碼中可以看到具體的邏輯還是特別清晰的。可以清楚地了解各個(gè)控件間的關(guān)系,基本上每一行代表著xib中的一根約束。

并且Masonry支持了一些省略和簡(jiǎn)寫(xiě):

如果是兩個(gè)控件的同一個(gè)位置(約束)之間的聯(lián)系,括號(hào)中可以只寫(xiě)以來(lái)的控件約束可以省略;

如果約束依賴(lài)的是同一個(gè)控件,那可以用and將兩個(gè)約束連在一行寫(xiě);

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

將上面的代碼最簡(jiǎn)可以寫(xiě)成如下

    [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);    }];

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

 

2.實(shí)現(xiàn)相互依賴(lài)的自動(dòng)布局,背景View的高度由自己子控件的Label能拉多長(zhǎng)決定。

簡(jiǎn)單的描述就是,label的左邊和頂部是依賴(lài)父控件grayView的。但是父控件grayView的底部是依賴(lài)子控件Label的。

上面右圖是IB頁(yè)面搭建的AutoLayout,但是按照xib的搭建的思路寫(xiě)出的代碼是有問(wèn)題的。

    [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);    }];

 上面的代碼會(huì)導(dǎo)致崩潰,原因就是上面的第4行依賴(lài)的contentLbl的約束還沒(méi)有搭建所以導(dǎo)致崩潰。在xib中會(huì)出現(xiàn)紅色箭頭的情況,就是約束錯(cuò)誤,在將約束調(diào)整正確后紅色箭頭會(huì)變成黃色箭頭,就是約束正確。 但是使用Masonry與xib不同,xib出現(xiàn)錯(cuò)誤可以容忍你改正,Masonry只要出現(xiàn)錯(cuò)誤就會(huì)馬上崩潰。 因此對(duì)于這種相互依賴(lài)的約束,下面的還沒(méi)建立就要約束他看似無(wú)法完成,實(shí)際的解決方案就是用子控件反過(guò)來(lái)依賴(lài)他也是可以的。 也就是說(shuō),你想讓父控件依賴(lài)子控件比他多10像素,和設(shè)置子控件依賴(lài)父控件比他少10像素是一個(gè)等價(jià)的概念,可以相互轉(zhuǎn)化。如果你是細(xì)心的網(wǎng)友,你會(huì)發(fā)現(xiàn)在xib中你雖然設(shè)置的是父控件依賴(lài)子控件,但實(shí)際的約束還是放在子控件里的。

修改后的代碼如下:

    [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.設(shè)置百分比的約束,即一個(gè)約束是另一個(gè)約束百分之多少。

這種約束一般適用于width和height。 對(duì)于屏幕的適配很有用,等于把以前算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);    }];

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

 

4.設(shè)置約束的更新

當(dāng)前的自動(dòng)布局第三方庫(kù)有多種,Masonry相比來(lái)說(shuō)也算是重量級(jí)的了。Masonry相比其他自動(dòng)布局的庫(kù)最大的優(yōu)點(diǎn)是在于約束的更新做的很好。

假設(shè)現(xiàn)在的約束是上面第2條時(shí)的約束,現(xiàn)在設(shè)置按鈕點(diǎn)擊更新約束代碼如下

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

如果給約束的變化設(shè)置約束,需要用UIView動(dòng)畫(huà)的block將 layoutIfNeed包裹住。而不是直接將約束更新包裹住。

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

所以u(píng)pdate要注意的是不要用新的方法添加了約束會(huì)與之前的約束相沖突。而remake需要注意的是你在remake里面寫(xiě)的約束必須是一個(gè)完整的約束,因?yàn)橹暗募s束全清空了。

如果沒(méi)有完全弄清兩個(gè)方法的區(qū)別則可能會(huì)寫(xiě)出以下代碼,這是錯(cuò)誤的

- (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];    }];}

因?yàn)樵瓉?lái)的make.width.equalTo(@200); 和本次的 make.width.equalTo(self.view).multipliedBy(0.5); 雖然都是設(shè)置width但是設(shè)置方法不同,所以會(huì)會(huì)新舊都保留導(dǎo)致沖突報(bào)錯(cuò)。

如果你不是在董鉑然博客園看到本文請(qǐng)點(diǎn)擊查看原文

 

5.設(shè)置優(yōu)先級(jí)和Label抗壓縮

有的時(shí)候Label的寬度或是內(nèi)部字體發(fā)生變化的時(shí)候,可能會(huì)出現(xiàn)XX... 這種情況,這是因?yàn)長(zhǎng)abel被壓縮了。Masonry有抗壓縮的設(shè)置,并且這個(gè)設(shè)置和Masonry的優(yōu)先級(jí)PRiority息息相關(guān)。iOS9字體的變化導(dǎo)致很多Label出現(xiàn)... ,如果當(dāng)初使用Masonry來(lái)設(shè)置布局并且設(shè)置了抗壓縮,那應(yīng)該就可以完全避免此問(wèn)題。

設(shè)置一個(gè)View,里面有一個(gè)子控件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);    }];

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

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

 

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

    [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行的優(yōu)先級(jí)大于第4行的優(yōu)先級(jí) 所以執(zhí)行第3行,Label并沒(méi)有被擠壓。

 

抗壓縮還有另一種設(shè)置方法 

    [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];

設(shè)置“右邊要比父控件少50” 的優(yōu)先級(jí)為1000以下, 然后在下面再寫(xiě)上一行水平方向抗壓縮的代碼。 這里要注意上面的“右邊比父控件少50”優(yōu)先級(jí)不能不寫(xiě),因?yàn)镸asonry這種類(lèi)型的代碼默認(rèn)優(yōu)先級(jí)都是1000,而下面UILayoutPriorityRequired的優(yōu)先級(jí)也是1000,那么下面的代碼就不起效果了。

 

其實(shí)還有更簡(jiǎn)單的設(shè)置方法,不用寫(xiě)水平方向抗壓縮,只需要將上面約束后面的優(yōu)先級(jí)改到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);    }];

因?yàn)閮?yōu)先級(jí)750對(duì)應(yīng)的優(yōu)先級(jí)枚舉是UILayoutPriorityDefaultHigh,可以理解成Masonry本身就有一種抗壓縮的保護(hù),優(yōu)先級(jí)是750。

    [contentLbl2 setContentCompressionResistancePriority:UILayoutPriorityDefaultHigh forAxis:UILayoutConstraintAxisHorizontal];

這行代碼應(yīng)該是所有l(wèi)abel默認(rèn)存在的。

所以以后如果想讓Label抗壓縮,直接把優(yōu)先級(jí)設(shè)置到750以下就OK了。

 

總結(jié):

1.Masonry的方法并不多,鏈?zhǔn)椒椒ǎ恳粋€(gè)點(diǎn)語(yǔ)法都是返回一個(gè)約束對(duì)象,一個(gè)個(gè)特定的約束是這個(gè)對(duì)象的屬性。

2.Masonry不同于xib搭建約束出現(xiàn)紅色還能調(diào)整,前者一出現(xiàn)問(wèn)題直接崩潰,將問(wèn)題卡在開(kāi)發(fā)階段。

3.Masonry建立約束前必須將父子關(guān)系搭建好,并且不能對(duì)還沒(méi)有設(shè)置約束的控件添加依賴(lài)。

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

未經(jīng)授權(quán)不得轉(zhuǎn)載


發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 阜城县| 周至县| 上杭县| 祁连县| 南汇区| 鄱阳县| 兴仁县| 织金县| 新泰市| 潢川县| 贵定县| 大宁县| 璧山县| 延吉市| 来凤县| 武平县| 琼海市| 邹城市| 信阳市| 定远县| 太白县| 万州区| 高邮市| 京山县| 太谷县| 建宁县| 贵德县| 吉安市| 广河县| 汾西县| 大姚县| 博野县| 秦皇岛市| 康保县| 北碚区| 襄垣县| 都江堰市| 张家界市| 普定县| 通州市| 焦作市|