iOS自動布局框架-Masonry詳解

原文

目前iOS開發(fā)中大多數(shù)頁面都已經(jīng)開始使用Interface Builder的方式進行UI開發(fā)了痊远,但是在一些變化比較復(fù)雜的頁面,還是需要通過代碼來進行UI開發(fā)的。而且有很多比較老的項目尤筐,本身就還在采用純代碼的方式進行開發(fā)畸肆。

而現(xiàn)在iPhone和iPad屏幕尺寸越來越多布卡,雖然開發(fā)者只需要根據(jù)屏幕點進行開發(fā),而不需要基于像素點進行UI開發(fā)惊来。但如果在項目中根據(jù)不同屏幕尺寸進行各種判斷攀痊,寫死坐標的話桐腌,這樣開發(fā)起來是很吃力的。

所以一般用純代碼開發(fā)UI的話蚕苇,一般都是配合一些自動化布局的框架進行屏幕適配哩掺。蘋果為我們提供的適配框架有:VFL、UIViewAutoresizing涩笤、Auto Layout嚼吞、Size Classes等。

其中Auto Layout是使用頻率最高的布局框架蹬碧,但是其也有弊端舱禽。就是在使用UILayoutConstraint的時候,會發(fā)現(xiàn)代碼量很多恩沽,而且大多都是重復(fù)性的代碼誊稚,以至于好多人都不想用這個框架。

后來Github上的出現(xiàn)了基于UILayoutConstraint封裝的第三方布局框架Masonry,Masonry使用起來非常方便里伯,本篇文章就詳細講一下Masonry的使用城瞎。

Masonry介紹

這篇文章只是簡單介紹Masonry,以及Masonry的使用疾瓮,并且會舉一些例子出來脖镀。但并不會涉及到Masonry的內(nèi)部實現(xiàn),以后會專門寫篇文章來介紹其內(nèi)部實現(xiàn)原理狼电,包括順便講一下鏈式語法蜒灰。

什么是Masonry

Masonry是一個對系統(tǒng)NSLayoutConstraint進行封裝的第三方自動布局框架肩碟,采用鏈式編程的方式提供給開發(fā)者API强窖。系統(tǒng)AutoLayout支持的操作削祈,Masonry都支持,相比系統(tǒng)API功能來說髓抑,Masonry是有過之而無不及未巫。

Masonry采取了鏈式編程的方式启昧,代碼理解起來非常清晰易懂劈伴,而且寫完之后代碼量看起來非常少密末。之前用NSLayoutConstraint寫很多代碼才能實現(xiàn)的布局,用Masonry最少一行代碼就可以搞定跛璧。下面看到Masonry的代碼就會發(fā)現(xiàn),太簡單易懂了刹碾。

Masonry是同時支持Mac和iOS兩個平臺的座柱,在這兩個平臺上都可以使用Masonry進行自動布局。我們可以從MASUtilities.h文件中色洞,看到下面的定義,這就是Masonry通過宏定義的方式锦针,區(qū)分兩個平臺獨有的一些關(guān)鍵字。

Github地址:https://github.com/SnapKit/Masonry

集成方式

Masonry支持CocoaPods悉盆,可以直接通過podfile文件進行集成馋吗,需要在CocoaPods中添加下面代碼:

pod?'Masonry'

Masonry學(xué)習(xí)建議

在UI開發(fā)中,純代碼和Interface Builder我都是用過的京髓,在開發(fā)過程中也積累了一些經(jīng)驗商架。對于初學(xué)者學(xué)習(xí)純代碼AutoLayout,我建議還是先學(xué)會Interface Builder方式的AutoLayout备图,領(lǐng)悟蘋果對自動布局的規(guī)則和思想赶袄,然后再把這套思想嵌套在純代碼上。這樣學(xué)習(xí)起來更好入手蒋困,也可以避免踩好多坑敬辣。

在項目中設(shè)置的AutoLayout約束,起到對視圖布局的標記作用村刨。設(shè)置好約束之后,程序運行過程中創(chuàng)建視圖時嵌牺,會根據(jù)設(shè)置好的約束計算frame龄糊,并渲染到視圖上。

所以在純代碼情況下枯饿,視圖設(shè)置的約束是否正確诡必,要以運行之后顯示的結(jié)果和打印的log為準奢方。

Masonry中的坑

在使用Masonry進行約束時,有一些是需要注意的稿蹲。

在使用Masonry添加約束之前鹊奖,需要在addSubview之后才能使用,否則會導(dǎo)致崩潰设哗。

在添加約束時初學(xué)者經(jīng)常會出現(xiàn)一些錯誤两蟀,約束出現(xiàn)問題的原因一般就是兩種:約束沖突和缺少約束。對于這兩種問題战虏,可以通過調(diào)試和log排查党涕。

之前使用Interface Builder添加約束膛堤,如果約束有錯誤直接就可以看出來,并且會以紅色或者黃色警告體現(xiàn)出來回懦。而Masonry則不會直觀的體現(xiàn)出來次企,而是以運行過程中崩潰或者打印異常log體現(xiàn)潜圃,所以這也是手寫代碼進行AutoLayout的一個缺點。

這個問題只能通過多敲代碼堵第,積攢純代碼進行AutoLayout的經(jīng)驗隧出,慢慢就用起來越來越得心應(yīng)手了胀瞪。

Masonry基礎(chǔ)使用

Masonry基礎(chǔ)API

mas_makeConstraints()????添加約束

mas_remakeConstraints()??移除之前的約束饲鄙,重新添加新的約束

mas_updateConstraints()??更新約束

equalTo()???????參數(shù)是對象類型圆雁,一般是視圖對象或者mas_width這樣的坐標系對象

mas_equalTo()???和上面功能相同伪朽,參數(shù)可以傳遞基礎(chǔ)數(shù)據(jù)類型對象,可以理解為比上面的API更強大

width()?????????用來表示寬度烈涮,例如代表view的寬度

mas_width()?????用來獲取寬度的值坚洽。和上面的區(qū)別在于,一個代表某個坐標系對象酪术,一個用來獲取坐標系對象的值

Auto Boxing

上面例如equalTo或者width這樣的,有時候需要涉及到使用mas_前綴橡疼,這在開發(fā)中需要注意作區(qū)分庐舟。

如果在當(dāng)前類引入#import "Masonry.h"之前,用下面兩種宏定義聲明一下挪略,就不需要區(qū)分mas_前綴杠娱。

//?定義這個常量,就可以不用在開發(fā)過程中使用"mas_"前綴摊求。

#define?MAS_SHORTHAND

//?定義這個常量室叉,就可以讓Masonry幫我們自動把基礎(chǔ)數(shù)據(jù)類型的數(shù)據(jù),自動裝箱為對象類型野来。

#define?MAS_SHORTHAND_GLOBALS

修飾語句

Masonry為了讓代碼使用和閱讀更容易理解踪旷,所以直接通過點語法就可以調(diào)用,還添加了and和with兩個方法搪锣。這兩個方法內(nèi)部實際上什么都沒干,只是在內(nèi)部將self直接返回灰追,功能就是為了更加方便閱讀狗超,對代碼執(zhí)行沒有實際作用努咐。

例如下面的例子:

make.top.and.bottom.equalTo(self.containerView).with.offset(padding);復(fù)制代碼

其內(nèi)部代碼實現(xiàn),實際上就是直接將self返回佩迟。

-?(MASConstraint?*)with?{

????return?self;

}

更新約束和布局

關(guān)于更新約束布局相關(guān)的API竿屹,主要用以下四個API:

-?(void)updateConstraintsIfNeeded??調(diào)用此方法,如果有標記為需要重新布局的約束秉溉,則立即進行重新布局碗誉,內(nèi)部會調(diào)用updateConstraints方法

-?(void)updateConstraints??????????重寫此方法哮缺,內(nèi)部實現(xiàn)自定義布局過程

-?(BOOL)needsUpdateConstraints?????當(dāng)前是否需要重新布局,內(nèi)部會判斷當(dāng)前有沒有被標記的約束

-?(void)setNeedsUpdateConstraints??標記需要進行重新布局復(fù)制代碼

關(guān)于UIView重新布局相關(guān)的API铛只,主要用以下三個API:

-?(void)setNeedsLayout??標記為需要重新布局

-?(void)layoutIfNeeded??查看當(dāng)前視圖是否被標記需要重新布局茎匠,有則在內(nèi)部調(diào)用layoutSubviews方法進行重新布局

-?(void)layoutSubviews??重寫當(dāng)前方法诵冒,在內(nèi)部完成重新布局操作復(fù)制代碼

Masonry示例代碼

Masonry本質(zhì)上就是對系統(tǒng)AutoLayout進行的封裝谊惭,包括里面很多的API侮东,都是對系統(tǒng)API進行了一次二次包裝豹芯。

typedef?NS_OPTIONS(NSInteger,?MASAttribute)?{

????MASAttributeLeft?=?1?<<?NSLayoutAttributeLeft,

????MASAttributeRight?=?1?<<?NSLayoutAttributeRight,

????MASAttributeTop?=?1?<<?NSLayoutAttributeTop,

????MASAttributeBottom?=?1?<<?NSLayoutAttributeBottom,

????MASAttributeLeading?=?1?<<?NSLayoutAttributeLeading,

????MASAttributeTrailing?=?1?<<?NSLayoutAttributeTrailing,

????MASAttributeWidth?=?1?<<?NSLayoutAttributeWidth,

????MASAttributeHeight?=?1?<<?NSLayoutAttributeHeight,

????MASAttributeCenterX?=?1?<<?NSLayoutAttributeCenterX,

????MASAttributeCenterY?=?1?<<?NSLayoutAttributeCenterY,

????MASAttributeBaseline?=?1?<<?NSLayoutAttributeBaseline,

};

常用方法

設(shè)置內(nèi)邊距

/**?

?設(shè)置yellow視圖和self.view等大铁蹈,并且有10的內(nèi)邊距握牧。

?注意根據(jù)UIView的坐標系,下面right和bottom進行了取反览徒。所以不能寫成下面這樣颂龙,否則right、bottom這兩個方向會出現(xiàn)問題躲叼。

?make.edges.equalTo(self.view).with.offset(10);

?除了下面例子中的offset()方法铅匹,還有針對不同坐標系的centerOffset()包斑、sizeOffset()罗丰、valueOffset()之類的方法萌抵。

?*/

[self.yellowView?mas_makeConstraints:^(MASConstraintMaker?*make)?{

????make.left.equalTo(self.view).with.offset(10);

????make.top.equalTo(self.view).with.offset(10);

????make.right.equalTo(self.view).with.offset(-10);

????make.bottom.equalTo(self.view).with.offset(-10);

}];

通過insets簡化設(shè)置內(nèi)邊距的方式

//?下面的方法和上面例子等價霎桅,區(qū)別在于使用insets()方法讨永。

[self.blueView?mas_makeConstraints:^(MASConstraintMaker?*make)?{

????//?下、右不需要寫負號揭糕,insets方法中已經(jīng)為我們做了取反的操作了揪漩。

????make.edges.equalTo(self.view).with.insets(UIEdgeInsetsMake(10,?10,?10,?10));

}];

更新約束

//?設(shè)置greenView的center和size奄容,這樣就可以達到簡單進行約束的目的

[self.greenView?mas_makeConstraints:^(MASConstraintMaker?*make)?{

????make.center.equalTo(self.view);

????//?這里通過mas_equalTo給size設(shè)置了基礎(chǔ)數(shù)據(jù)類型的參數(shù)锨侯,參數(shù)為CGSize的結(jié)構(gòu)體

????make.size.mas_equalTo(CGSizeMake(300,?300));

}];

//?為了更清楚的看出約束變化的效果囚痴,在顯示兩秒后更新約束深滚。

dispatch_after(dispatch_time(DISPATCH_TIME_NOW,?(int64_t)(2.f?*?NSEC_PER_SEC)),?dispatch_get_main_queue(),?^{

????[self.greenView?mas_updateConstraints:^(MASConstraintMaker?*make)?{

????????make.centerX.equalTo(self.view).offset(100);

????????make.size.mas_equalTo(CGSizeMake(100,?100));

????}];

});

大于等于和小于等于某個值的約束

[self.textLabel?mas_makeConstraints:^(MASConstraintMaker?*make)?{

????make.center.equalTo(self.view);

????//?設(shè)置寬度小于等于200

????make.width.lessThanOrEqualTo(@200);

????//?設(shè)置高度大于等于10

????make.height.greaterThanOrEqualTo(@(10));

}];

self.textLabel.text = @"這是測試的字符串血柳。能看到1、2根吁、3個步驟击敌,第一步當(dāng)然是上傳照片了,要上傳正面近照哦衡瓶。上傳后,網(wǎng)站會自動識別你的面部诚撵,如果覺得識別的不準寿烟,你還可以手動修改一下。左邊可以看到16項修改參數(shù)徘六,最上面是整體修改嘴高,你也可以根據(jù)自己的意愿單獨修改某項拴驮,將鼠標放到選項上面套啤,右邊的預(yù)覽圖會顯示相應(yīng)的位置萄涯。";

textLabel只需要設(shè)置一個屬性即可

self.textLabel.numberOfLines?=?0;

使用基礎(chǔ)數(shù)據(jù)類型當(dāng)做參數(shù)

/**?

?如果想使用基礎(chǔ)數(shù)據(jù)類型當(dāng)做參數(shù),Masonry為我們提供了"mas_xx"格式的宏定義。

?這些宏定義會將傳入的基礎(chǔ)數(shù)據(jù)類型轉(zhuǎn)換為NSNumber類型燃乍,這個過程叫做封箱(Auto?Boxing)。


?"mas_xx"開頭的宏定義,內(nèi)部都是通過MASBoxValue()函數(shù)實現(xiàn)的。

?這樣的宏定義主要有四個,分別是mas_equalTo()蛮浑、mas_offset()和大于等于、小于等于四個蕴掏。

?*/

[self.redView?mas_makeConstraints:^(MASConstraintMaker?*make)?{

????make.center.equalTo(self.view);

????make.width.mas_equalTo(100);

????make.height.mas_equalTo(100);

}];

設(shè)置約束優(yōu)先級

/**?

?Masonry為我們提供了三個默認的方法,priorityLow()饶唤、priorityMedium()募狂、priorityHigh()祸穷,這三個方法內(nèi)部對應(yīng)著不同的默認優(yōu)先級。

?除了這三個方法,我們也可以自己設(shè)置優(yōu)先級的值车份,可以通過priority()方法來設(shè)置。

?*/

[self.redView?mas_makeConstraints:^(MASConstraintMaker?*make)?{

????make.center.equalTo(self.view);

????make.width.equalTo(self.view).priorityLow();

????make.width.mas_equalTo(20).priorityHigh();

????make.height.equalTo(self.view).priority(200);

????make.height.mas_equalTo(100).priority(1000);

}];

Masonry也幫我們定義好了一些默認的優(yōu)先級常量缎除,分別對應(yīng)著不同的數(shù)值盈蛮,優(yōu)先級最大數(shù)值是1000殊轴。

static?const?MASLayoutPriority?MASLayoutPriorityRequired?=?UILayoutPriorityRequired;

static?const?MASLayoutPriority?MASLayoutPriorityDefaultHigh?=?UILayoutPriorityDefaultHigh;

static?const?MASLayoutPriority?MASLayoutPriorityDefaultMedium?=?500;

static?const?MASLayoutPriority?MASLayoutPriorityDefaultLow?=?UILayoutPriorityDefaultLow;

static?const?MASLayoutPriority?MASLayoutPriorityFittingSizeLevel?=?UILayoutPriorityFittingSizeLevel;復(fù)制代碼

設(shè)置約束比例

//?設(shè)置當(dāng)前約束值乘以多少樊零,例如這個例子是redView的寬度是self.view寬度的0.2倍。

[self.redView?mas_makeConstraints:^(MASConstraintMaker?*make)?{

????make.center.equalTo(self.view);

????make.height.mas_equalTo(30);

????make.width.equalTo(self.view).multipliedBy(0.2);

}];

小練習(xí)

子視圖等高練習(xí)

/**?

?下面的例子是通過給equalTo()方法傳入一個數(shù)組沉衣,設(shè)置數(shù)組中子視圖及當(dāng)前make對應(yīng)的視圖之間等高拔疚。

?需要注意的是稚失,下面block中設(shè)置邊距的時候句各,應(yīng)該用insets來設(shè)置旬昭,而不是用offset问拘。

?因為用offset設(shè)置right和bottom的邊距時骤坐,這兩個值應(yīng)該是負數(shù),所以如果通過offset來統(tǒng)一設(shè)置值會有問題拌夏。

?*/

CGFloat?padding?=?LXZViewPadding;

[self.redView?mas_makeConstraints:^(MASConstraintMaker?*make)?{

????make.left.right.top.equalTo(self.view).insets(UIEdgeInsetsMake(padding,?padding,?0,?padding));

????make.bottom.equalTo(self.blueView.mas_top).offset(-padding);

}];

[self.blueView?mas_makeConstraints:^(MASConstraintMaker?*make)?{

????make.left.right.equalTo(self.view).insets(UIEdgeInsetsMake(0,?padding,?0,?padding));

????make.bottom.equalTo(self.yellowView.mas_top).offset(-padding);

}];

/**?

?下面設(shè)置make.height的數(shù)組是關(guān)鍵,通過這個數(shù)組可以設(shè)置這三個視圖高度相等。其他例如寬度之類的愈腾,也是類似的方式虱黄。

?*/

[self.yellowView?mas_makeConstraints:^(MASConstraintMaker?*make)?{

????make.left.right.bottom.equalTo(self.view).insets(UIEdgeInsetsMake(0,?padding,?padding,?padding));

????make.height.equalTo(@[self.blueView,?self.redView]);

}];

子視圖垂直居中練習(xí)

/**?

?要求:(這個例子是在其他人博客里看到的,然后按照要求自己寫了下面這段代碼)

?兩個視圖相對于父視圖垂直居中仅醇,并且兩個視圖以及父視圖之間的邊距均為10,高度為150叶摄,兩個視圖寬度相等。

?*/

CGFloat?padding?=?10.f;

[self.blueView?mas_makeConstraints:^(MASConstraintMaker?*make)?{

????make.centerY.equalTo(self.view);

????make.left.equalTo(self.view).mas_offset(padding);

????make.right.equalTo(self.redView.mas_left).mas_offset(-padding);

????make.width.equalTo(self.redView);

????make.height.mas_equalTo(150);

}];

[self.redView?mas_makeConstraints:^(MASConstraintMaker?*make)?{

????make.centerY.equalTo(self.view);

????make.right.equalTo(self.view).mas_offset(-padding);

????make.width.equalTo(self.blueView);

????make.height.mas_equalTo(150);

}];

UITableView動態(tài)Cell高度

在iOS UI開發(fā)過程中,UITableView的動態(tài)Cell高度一直都是個問題裸燎。實現(xiàn)這樣的需求,實現(xiàn)方式有很多種移稳,只是實現(xiàn)起來復(fù)雜程度和性能的區(qū)別。

在不考慮性能的情況下,tableView動態(tài)Cell高度体斩,可以采取估算高度的方式。如果通過估算高度的方式實現(xiàn)的話蹬敲,無論是純代碼還是Interface Builder,都只需要兩行代碼就可以完成Cell自動高度適配瘪校。

實現(xiàn)方式:

需要設(shè)置tableView的rowHeight屬性伸辟,這里設(shè)置為自動高度信夫,告訴系統(tǒng)Cell的高度是不固定的脐彩,需要系統(tǒng)幫我們進行計算惠奸。然后設(shè)置tableView的estimatedRowHeight屬性梗掰,設(shè)置一個估計的高度。(我這里用的代理方法埂陆,實際上都一樣)

原理:

這樣的話,在tableView被創(chuàng)建之后,系統(tǒng)會根據(jù)estimatedRowHeight屬性設(shè)置的值民鼓,為tableView設(shè)置一個估計的值。然后在Cell顯示的時候再獲取Cell的高度,并刷新tableView的contentSize峭状。

-?(void)tableViewConstraints?{

????[self.tableView?mas_makeConstraints:^(MASConstraintMaker?*make)?{

????????make.edges.equalTo(self.view);

????}];

}

-?(NSInteger)tableView:(UITableView?*)tableView?numberOfRowsInSection:(NSInteger)section?{

????return?self.dataList.count;

}

-?(MasonryTableViewCell?*)tableView:(UITableView?*)tableView?cellForRowAtIndexPath:(NSIndexPath?*)indexPath?{

????MasonryTableViewCell?*cell?=?[tableView?dequeueReusableCellWithIdentifier:LXZTableViewCellIdentifier];

????[cell?reloadViewWithText:self.dataList[indexPath.row]];

????return?cell;

}

//?需要注意的是,這個代理方法和直接返回當(dāng)前Cell高度的代理方法并不一樣杂伟。

//?這個代理方法會將當(dāng)前所有Cell的高度都預(yù)估出來赫粥,而不是只計算顯示的Cell灵迫,所以這種方式對性能消耗還是很大的瀑粥。

//?所以通過設(shè)置estimatedRowHeight屬性的方式狞换,和這種代理方法的方式,最后性能消耗都是一樣的膨报。

-?(CGFloat)tableView:(UITableView?*)tableView?estimatedHeightForRowAtIndexPath:(NSIndexPath?*)indexPath?{

????return?50.f;

}

-?(UITableView?*)tableView?{

????if?(!_tableView)?{

????????_tableView?=?[[UITableView?alloc]?initWithFrame:CGRectZero?style:UITableViewStylePlain];

????????_tableView.delegate?=?self;

????????_tableView.dataSource?=?self;

????????//?設(shè)置tableView自動高度

????????_tableView.rowHeight?=?UITableViewAutomaticDimension;

????????[_tableView?registerClass:[MasonryTableViewCell?class]?forCellReuseIdentifier:LXZTableViewCellIdentifier];

????????[self.view?addSubview:_tableView];

????}

????return?_tableView;

}復(fù)制代碼

UIScrollView自動布局

之前聽很多人說過UIScrollView很麻煩弛矛,然而我并沒有感覺到有多麻煩(并非裝逼)。我感覺說麻煩的人可能根本就沒試過吧万俗,只是覺得很麻煩而已。

我這里就講一下兩種進行UIScrollView自動布局的方案库倘,并且會講一下自動布局的技巧杆勇,只要掌握技巧,布局其實很簡單关霸。

布局小技巧:

給UIScrollView添加的約束是定義其frame,設(shè)置contentSize是定義其內(nèi)部大小佳遣。UIScrollView進行addSubview操作,都是將其子視圖添加到contentView上。

所以风宁,添加到UIScrollView上的子視圖,對UIScrollView添加的約束都是作用于contentView上的。只需要按照這樣的思路給UIScrollView設(shè)置約束幽崩,就可以掌握設(shè)置約束的技巧了。

提前設(shè)置contentSize

//?提前設(shè)置好UIScrollView的contentSize柠贤,并設(shè)置UIScrollView自身的約束

self.scrollView.contentSize?=?CGSizeMake(1000,?1000);

[self.scrollView?mas_makeConstraints:^(MASConstraintMaker?*make)?{

????make.edges.equalTo(self.view);

}];

//?雖然redView的get方法內(nèi)部已經(jīng)執(zhí)行過addSubview操作臼勉,但是UIView始終以最后一次添加的父視圖為準,也就是redView始終是在最后一次添加的父視圖上瓢谢。

[self.scrollView?addSubview:self.redView];

[self.redView?mas_makeConstraints:^(MASConstraintMaker?*make)?{

????make.left.top.equalTo(self.scrollView);

????make.width.height.mas_equalTo(200);

}];

[self.scrollView?addSubview:self.blueView];

[self.blueView?mas_makeConstraints:^(MASConstraintMaker?*make)?{

????make.left.equalTo(self.redView.mas_right);

????make.top.equalTo(self.scrollView);

????make.width.height.equalTo(self.redView);

}];

[self.scrollView?addSubview:self.greenView];

[self.greenView?mas_makeConstraints:^(MASConstraintMaker?*make)?{

????make.left.equalTo(self.scrollView);

????make.top.equalTo(self.redView.mas_bottom);

????make.width.height.equalTo(self.redView);

}];

自動contentSize

上面的例子是提前設(shè)置好UIScrollView的contentSize的內(nèi)部size论笔,然后直接向里面addSubview。但是這有個要求就是最楷,需要提前知道contentSize的大小烈评,不然沒法設(shè)置础倍。

這個例子中將會展示動態(tài)改變contentSize的大小犹菇,內(nèi)部視圖有多少contentSize就自動擴充到多大揭芍。

這種方式的實現(xiàn)称杨,主要是依賴于創(chuàng)建一個containerView內(nèi)容視圖悬而,并添加到UIScrollView上作為子視圖锭汛。UIScrollView原來的子視圖都添加到containerView上唤殴,并且和這個視圖設(shè)置約束。

因為對UIScrollView進行addSubview操作的時候蔚袍,本質(zhì)上是往其contentView上添加配名。也就是containerView的父視圖是contentView,通過containerView撐起contentView視圖的大小闰蚕,以此來實現(xiàn)動態(tài)改變contentSize没陡。

//?在進行約束的時候索赏,要對containerView的上下左右都添加和子視圖的約束潜腻,以便確認containerView的邊界區(qū)域融涣。

[self.scrollView?mas_makeConstraints:^(MASConstraintMaker?*make)?{

????make.edges.equalTo(self.view);

}];

CGFloat?padding?=?LXZViewPadding;

[self.containerView?mas_makeConstraints:^(MASConstraintMaker?*make)?{

????make.edges.equalTo(self.scrollView).insets(UIEdgeInsetsMake(padding,?padding,?padding,?padding));

}];

[self.containerView?addSubview:self.greenView];

[self.greenView?mas_makeConstraints:^(MASConstraintMaker?*make)?{

????make.top.left.equalTo(self.containerView).offset(padding);

????make.size.mas_equalTo(CGSizeMake(250,?250));

}];

[self.containerView?addSubview:self.redView];

[self.redView?mas_makeConstraints:^(MASConstraintMaker?*make)?{

????make.top.equalTo(self.containerView).offset(padding);

????make.left.equalTo(self.greenView.mas_right).offset(padding);

????make.size.equalTo(self.greenView);

????make.right.equalTo(self.containerView).offset(-padding);

}];

[self.containerView?addSubview:self.yellowView];

[self.yellowView?mas_makeConstraints:^(MASConstraintMaker?*make)?{

????make.left.equalTo(self.containerView).offset(padding);

????make.top.equalTo(self.greenView.mas_bottom).offset(padding);

????make.size.equalTo(self.greenView);

????make.bottom.equalTo(self.containerView).offset(-padding);

}];

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末剃斧,一起剝皮案震驚了整個濱河市忽你,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌根蟹,老刑警劉巖简逮,帶你破解...
    沈念sama閱讀 212,454評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異沛婴,居然都是意外死亡嘁灯,警方通過查閱死者的電腦和手機躲舌,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,553評論 3 385
  • 文/潘曉璐 我一進店門没卸,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人诀拭,你說我怎么就攤上這事煤蚌∥咀” “怎么了?”我有些...
    開封第一講書人閱讀 157,921評論 0 348
  • 文/不壞的土叔 我叫張陵翰苫,是天一觀的道長奏窑。 經(jīng)常有香客問我析恋,道長助隧,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,648評論 1 284
  • 正文 為了忘掉前任巍实,我火速辦了婚禮哩牍,結(jié)果婚禮上膝昆,老公的妹妹穿的比我還像新娘。我一直安慰自己妹窖,他們只是感情好收叶,可當(dāng)我...
    茶點故事閱讀 65,770評論 6 386
  • 文/花漫 我一把揭開白布判没。 她就那樣靜靜地躺著澄峰,像睡著了一般。 火紅的嫁衣襯著肌膚如雪耻蛇。 梳的紋絲不亂的頭發(fā)上胞此,一...
    開封第一講書人閱讀 49,950評論 1 291
  • 那天漱牵,我揣著相機與錄音,去河邊找鬼刁赦。 笑死甚脉,一個胖子當(dāng)著我的面吹牛铆农,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播猴凹,決...
    沈念sama閱讀 39,090評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼郊霎,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了进倍?” 一聲冷哼從身側(cè)響起背捌,我...
    開封第一講書人閱讀 37,817評論 0 268
  • 序言:老撾萬榮一對情侶失蹤毡庆,失蹤者是張志新(化名)和其女友劉穎烙如,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蝇刀,經(jīng)...
    沈念sama閱讀 44,275評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡吞琐,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,592評論 2 327
  • 正文 我和宋清朗相戀三年站粟,在試婚紗的時候發(fā)現(xiàn)自己被綠了曾雕。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片剖张。...
    茶點故事閱讀 38,724評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡搔弄,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出倒庵,到底是詐尸還是另有隱情,我是刑警寧澤貌亭,帶...
    沈念sama閱讀 34,409評論 4 333
  • 正文 年R本政府宣布,位于F島的核電站失晴,受9級特大地震影響拘央,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜拆又,卻給世界環(huán)境...
    茶點故事閱讀 40,052評論 3 316
  • 文/蒙蒙 一帖族、第九天 我趴在偏房一處隱蔽的房頂上張望挡爵。 院中可真熱鬧茶鹃,春花似錦、人聲如沸挣郭。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,815評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至肤无,卻和暖如春先蒋,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背宛渐。 一陣腳步聲響...
    開封第一講書人閱讀 32,043評論 1 266
  • 我被黑心中介騙來泰國打工竞漾, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留眯搭,地道東北人。 一個月前我還...
    沈念sama閱讀 46,503評論 2 361
  • 正文 我出身青樓业岁,卻偏偏與公主長得像鳞仙,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子笔时,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,627評論 2 350