精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

iOS自動布局框架 – Masonry詳解

移動開發(fā) iOS
一般用純代碼開發(fā)UI的話,一般都是配合一些自動化布局的框架進(jìn)行屏幕適配。蘋果為我們提供的適配框架有:VFL、UIViewAutoresizing、Auto Layout、Size Classes等。后來Github上的出現(xiàn)了基于UILayoutConstraint封裝的第三方布局框架Masonry,Masonry使用起來非常方便,本篇文章就詳細(xì)講一下Masonry的使用

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

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

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

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

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

 

 

[[182259]] 

Masonry介紹

這篇文章只是簡單介紹Masonry,以及Masonry的使用,并且會舉一些例子出來。但并不會涉及到Masonry的內(nèi)部實(shí)現(xiàn),以后會專門寫篇文章來介紹其內(nèi)部實(shí)現(xiàn)原理,包括順便講一下鏈?zhǔn)秸Z法。

什么是Masonry

Masonry是一個對系統(tǒng)NSLayoutConstraint進(jìn)行封裝的第三方自動布局框架,采用鏈?zhǔn)骄幊痰姆绞教峁┙o開發(fā)者API。系統(tǒng)AutoLayout支持的操作,Masonry都支持,相比系統(tǒng)API功能來說,Masonry是有過之而無不及。

Masonry采取了鏈?zhǔn)骄幊痰姆绞剑a理解起來非常清晰易懂,而且寫完之后代碼量看起來非常少。之前用NSLayoutConstraint寫很多代碼才能實(shí)現(xiàn)的布局,用Masonry最少一行代碼就可以搞定。下面看到Masonry的代碼就會發(fā)現(xiàn),太簡單易懂了。

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

  1. #if TARGET_OS_IPHONE     
  2.     #import 
  3.     #define MAS_VIEW UIView 
  4.     #define MASEdgeInsets UIEdgeInsets 
  5. #elif TARGET_OS_MAC 
  6.     #import 
  7.     #define MAS_VIEW NSView 
  8.     #define MASEdgeInsets NSEdgeInsets 
  9. #endif  

Github地址:

https://github.com/SnapKit/Masonry

集成方式

Masonry支持CocoaPods,可以直接通過podfile文件進(jìn)行集成,需要在CocoaPods中添加下面代碼:

  1. pod 'Masonry' 

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

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

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

所以在純代碼情況下,視圖設(shè)置的約束是否正確,要以運(yùn)行之后顯示的結(jié)果和打印的log為準(zhǔn)。

Masonry中的坑

在使用Masonry進(jìn)行約束時,有一些是需要注意的。

  1. 在使用Masonry添加約束之前,需要在addSubview之后才能使用,否則會導(dǎo)致崩潰。
  2. 在添加約束時初學(xué)者經(jīng)常會出現(xiàn)一些錯誤,約束出現(xiàn)問題的原因一般就是兩種:約束沖突和缺少約束。對于這兩種問題,可以通過調(diào)試和log排查。
  3. 之前使用Interface Builder添加約束,如果約束有錯誤直接就可以看出來,并且會以紅色或者黃色警告體現(xiàn)出來。而Masonry則不會直觀的體現(xiàn)出來,而是以運(yùn)行過程中崩潰或者打印異常log體現(xiàn),所以這也是手寫代碼進(jìn)行AutoLayout的一個缺點(diǎn)。

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

Masonry基礎(chǔ)使用

Masonry基礎(chǔ)API

  1. mas_makeConstraints()    添加約束 
  2. mas_remakeConstraints()  移除之前的約束,重新添加新的約束 
  3. mas_updateConstraints()  更新約束 
  4.   
  5. equalTo()       參數(shù)是對象類型,一般是視圖對象或者mas_width這樣的坐標(biāo)系對象 
  6. mas_equalTo()   和上面功能相同,參數(shù)可以傳遞基礎(chǔ)數(shù)據(jù)類型對象,可以理解為比上面的API更強(qiáng)大 
  7.   
  8. width()         用來表示寬度,例如代表view的寬度 
  9. mas_width()     用來獲取寬度的值。和上面的區(qū)別在于,一個代表某個坐標(biāo)系對象,一個用來獲取坐標(biāo)系對象的值  

Auto Boxing

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

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

  1. // 定義這個常量,就可以不用在開發(fā)過程中使用"mas_"前綴。 
  2. #define MAS_SHORTHAND 
  3. // 定義這個常量,就可以讓Masonry幫我們自動把基礎(chǔ)數(shù)據(jù)類型的數(shù)據(jù),自動裝箱為對象類型。 
  4. #define MAS_SHORTHAND_GLOBALS  

修飾語句

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

例如下面的例子:

  1. make.top.and.bottom.equalTo(self.containerView).with.offset(padding); 

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

  1. - (MASConstraint *)with { 
  2.     return self; 
  3.  

更新約束和布局

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

  1. - (void)updateConstraintsIfNeeded  調(diào)用此方法,如果有標(biāo)記為需要重新布局的約束,則立即進(jìn)行重新布局,內(nèi)部會調(diào)用updateConstraints方法 
  2. - (void)updateConstraints          重寫此方法,內(nèi)部實(shí)現(xiàn)自定義布局過程 
  3. - (BOOL)needsUpdateConstraints     當(dāng)前是否需要重新布局,內(nèi)部會判斷當(dāng)前有沒有被標(biāo)記的約束 
  4. - (void)setNeedsUpdateConstraints  標(biāo)記需要進(jìn)行重新布局  

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

  1. - (void)setNeedsLayout  標(biāo)記為需要重新布局 
  2. - (void)layoutIfNeeded  查看當(dāng)前視圖是否被標(biāo)記需要重新布局,有則在內(nèi)部調(diào)用layoutSubviews方法進(jìn)行重新布局 
  3. - (void)layoutSubviews  重寫當(dāng)前方法,在內(nèi)部完成重新布局操作  

Masonry示例代碼

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

  1. Masonry本質(zhì)上就是對系統(tǒng)AutoLayout進(jìn)行的封裝,包括里面很多的API,都是對系統(tǒng)API進(jìn)行了一次二次包裝。 
  2. typedef NS_OPTIONS(NSInteger, MASAttribute) { 
  3.     MASAttributeLeft = 1 << NSLayoutAttributeLeft, 
  4.     MASAttributeRight = 1 << NSLayoutAttributeRight, 
  5.     MASAttributeTop = 1 << NSLayoutAttributeTop, 
  6.     MASAttributeBottom = 1 << NSLayoutAttributeBottom, 
  7.     MASAttributeLeading = 1 << NSLayoutAttributeLeading, 
  8.     MASAttributeTrailing = 1 << NSLayoutAttributeTrailing, 
  9.     MASAttributeWidth = 1 << NSLayoutAttributeWidth, 
  10.     MASAttributeHeight = 1 << NSLayoutAttributeHeight, 
  11.     MASAttributeCenterX = 1 << NSLayoutAttributeCenterX, 
  12.     MASAttributeCenterY = 1 << NSLayoutAttributeCenterY, 
  13.     MASAttributeBaseline = 1 << NSLayoutAttributeBaseline, 
  14. };  

常用方法

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

  1. /** 
  2. 設(shè)置yellow視圖和self.view等大,并且有10的內(nèi)邊距。 
  3. 注意根據(jù)UIView的坐標(biāo)系,下面right和bottom進(jìn)行了取反。所以不能寫成下面這樣,否則right、bottom這兩個方向會出現(xiàn)問題。 
  4. make.edges.equalTo(self.view).with.offset(10); 
  5.   
  6. 除了下面例子中的offset()方法,還有針對不同坐標(biāo)系的centerOffset()、sizeOffset()、valueOffset()之類的方法。 
  7. */ 
  8. [self.yellowView mas_makeConstraints:^(MASConstraintMaker *make) { 
  9.     make.left.equalTo(self.view).with.offset(10); 
  10.     make.top.equalTo(self.view).with.offset(10); 
  11.     make.right.equalTo(self.view).with.offset(-10); 
  12.     make.bottom.equalTo(self.view).with.offset(-10); 
  13. }];  

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

  1. // 下面的方法和上面例子等價,區(qū)別在于使用insets()方法。 
  2. [self.blueView mas_makeConstraints:^(MASConstraintMaker *make) { 
  3.     // 下、右不需要寫負(fù)號,insets方法中已經(jīng)為我們做了取反的操作了。 
  4.     make.edges.equalTo(self.view).with.insets(UIEdgeInsetsMake(10, 10, 10, 10)); 
  5. }];  

更新約束

  1. // 設(shè)置greenView的center和size,這樣就可以達(dá)到簡單進(jìn)行約束的目的 
  2. [self.greenView mas_makeConstraints:^(MASConstraintMaker *make) { 
  3.     make.center.equalTo(self.view); 
  4.     // 這里通過mas_equalTo給size設(shè)置了基礎(chǔ)數(shù)據(jù)類型的參數(shù),參數(shù)為CGSize的結(jié)構(gòu)體 
  5.     make.size.mas_equalTo(CGSizeMake(300, 300)); 
  6. }]; 
  7.   
  8. // 為了更清楚的看出約束變化的效果,在顯示兩秒后更新約束。 
  9. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.f * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 
  10.     [self.greenView mas_updateConstraints:^(MASConstraintMaker *make) { 
  11.         make.centerX.equalTo(self.view).offset(100); 
  12.         make.size.mas_equalTo(CGSizeMake(100, 100)); 
  13.     }]; 
  14. });  

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

  1. [self.textLabel mas_makeConstraints:^(MASConstraintMaker *make) { 
  2.     make.center.equalTo(self.view); 
  3.     // 設(shè)置寬度小于等于200 
  4.     make.width.lessThanOrEqualTo(@200); 
  5.     // 設(shè)置高度大于等于10 
  6.     make.height.greaterThanOrEqualTo(@(10)); 
  7. }]; 
  8.   
  9. self.textLabel.text = @"這是測試的字符串。能看到1、2、3個步驟,第一步當(dāng)然是上傳照片了,要上傳正面近照哦。上傳后,網(wǎng)站會自動識別你的面部,如果覺得識別的不準(zhǔn),你還可以手動修改一下。左邊可以看到16項(xiàng)修改參數(shù),最上面是整體修改,你也可以根據(jù)自己的意愿單獨(dú)修改某項(xiàng),將鼠標(biāo)放到選項(xiàng)上面,右邊的預(yù)覽圖會顯示相應(yīng)的位置。"

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

  1. self.textLabel.numberOfLines = 0; 

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

  1. /** 
  2. 如果想使用基礎(chǔ)數(shù)據(jù)類型當(dāng)做參數(shù),Masonry為我們提供了"mas_xx"格式的宏定義。 
  3. 這些宏定義會將傳入的基礎(chǔ)數(shù)據(jù)類型轉(zhuǎn)換為NSNumber類型,這個過程叫做封箱(Auto Boxing)。 
  4.   
  5. "mas_xx"開頭的宏定義,內(nèi)部都是通過MASBoxValue()函數(shù)實(shí)現(xiàn)的。 
  6. 這樣的宏定義主要有四個,分別是mas_equalTo()、mas_offset()和大于等于、小于等于四個。 
  7. */ 
  8. [self.redView mas_makeConstraints:^(MASConstraintMaker *make) { 
  9.     make.center.equalTo(self.view); 
  10.     make.width.mas_equalTo(100); 
  11.     make.height.mas_equalTo(100); 
  12. }]; 

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

  1. /** 
  2. Masonry為我們提供了三個默認(rèn)的方法,priorityLow()、priorityMedium()、priorityHigh(),這三個方法內(nèi)部對應(yīng)著不同的默認(rèn)優(yōu)先級。 
  3. 除了這三個方法,我們也可以自己設(shè)置優(yōu)先級的值,可以通過priority()方法來設(shè)置。 
  4. */ 
  5. [self.redView mas_makeConstraints:^(MASConstraintMaker *make) { 
  6.     make.center.equalTo(self.view); 
  7.     make.width.equalTo(self.view).priorityLow(); 
  8.     make.width.mas_equalTo(20).priorityHigh(); 
  9.     make.height.equalTo(self.view).priority(200); 
  10.     make.height.mas_equalTo(100).priority(1000); 
  11. }]; 
  12.  
  13. Masonry也幫我們定義好了一些默認(rèn)的優(yōu)先級常量,分別對應(yīng)著不同的數(shù)值,優(yōu)先級最大數(shù)值是1000。 
  14. static const MASLayoutPriority MASLayoutPriorityRequired = UILayoutPriorityRequired; 
  15. static const MASLayoutPriority MASLayoutPriorityDefaultHigh = UILayoutPriorityDefaultHigh; 
  16. static const MASLayoutPriority MASLayoutPriorityDefaultMedium = 500; 
  17. static const MASLayoutPriority MASLayoutPriorityDefaultLow = UILayoutPriorityDefaultLow; 
  18. static const MASLayoutPriority MASLayoutPriorityFittingSizeLevel = UILayoutPriorityFittingSizeLevel; 

 設(shè)置約束比例

  1. // 設(shè)置當(dāng)前約束值乘以多少,例如這個例子是redView的寬度是self.view寬度的0.2倍。 
  2. [self.redView mas_makeConstraints:^(MASConstraintMaker *make) { 
  3.     make.center.equalTo(self.view); 
  4.     make.height.mas_equalTo(30); 
  5.     make.width.equalTo(self.view).multipliedBy(0.2); 
  6. }]; 

 小練習(xí)

子視圖等高練習(xí)

  1. /** 
  2. 下面的例子是通過給equalTo()方法傳入一個數(shù)組,設(shè)置數(shù)組中子視圖及當(dāng)前make對應(yīng)的視圖之間等高。 
  3.   
  4. 需要注意的是,下面block中設(shè)置邊距的時候,應(yīng)該用insets來設(shè)置,而不是用offset。 
  5. 因?yàn)橛胦ffset設(shè)置right和bottom的邊距時,這兩個值應(yīng)該是負(fù)數(shù),所以如果通過offset來統(tǒng)一設(shè)置值會有問題。 
  6. */ 
  7. CGFloat padding = LXZViewPadding; 
  8. [self.redView mas_makeConstraints:^(MASConstraintMaker *make) { 
  9.     make.left.right.top.equalTo(self.view).insets(UIEdgeInsetsMake(padding, padding, 0, padding)); 
  10.     make.bottom.equalTo(self.blueView.mas_top).offset(-padding); 
  11. }]; 
  12.   
  13. [self.blueView mas_makeConstraints:^(MASConstraintMaker *make) { 
  14.     make.left.right.equalTo(self.view).insets(UIEdgeInsetsMake(0, padding, 0, padding)); 
  15.     make.bottom.equalTo(self.yellowView.mas_top).offset(-padding); 
  16. }]; 
  17.   
  18. /** 
  19. 下面設(shè)置make.height的數(shù)組是關(guān)鍵,通過這個數(shù)組可以設(shè)置這三個視圖高度相等。其他例如寬度之類的,也是類似的方式。 
  20. */ 
  21. [self.yellowView mas_makeConstraints:^(MASConstraintMaker *make) { 
  22.     make.left.right.bottom.equalTo(self.view).insets(UIEdgeInsetsMake(0, padding, padding, padding)); 
  23.     make.height.equalTo(@[self.blueView, self.redView]); 
  24. }]; 

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

  1. /** 
  2. 要求:(這個例子是在其他人博客里看到的,然后按照要求自己寫了下面這段代碼) 
  3. 兩個視圖相對于父視圖垂直居中,并且兩個視圖以及父視圖之間的邊距均為10,高度為150,兩個視圖寬度相等。 
  4. */ 
  5. CGFloat padding = 10.f; 
  6. [self.blueView mas_makeConstraints:^(MASConstraintMaker *make) { 
  7.     make.centerY.equalTo(self.view); 
  8.     make.left.equalTo(self.view).mas_offset(padding); 
  9.     make.right.equalTo(self.redView.mas_left).mas_offset(-padding); 
  10.     make.width.equalTo(self.redView); 
  11.     make.height.mas_equalTo(150); 
  12. }]; 
  13.   
  14. [self.redView mas_makeConstraints:^(MASConstraintMaker *make) { 
  15.     make.centerY.equalTo(self.view); 
  16.     make.right.equalTo(self.view).mas_offset(-padding); 
  17.     make.width.equalTo(self.blueView); 
  18.     make.height.mas_equalTo(150); 
  19. }]; 

 UITableView動態(tài)Cell高度

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

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

實(shí)現(xiàn)方式:

需要設(shè)置tableView的rowHeight屬性,這里設(shè)置為自動高度,告訴系統(tǒng)Cell的高度是不固定的,需要系統(tǒng)幫我們進(jìn)行計算。然后設(shè)置tableView的estimatedRowHeight屬性,設(shè)置一個估計的高度。(我這里用的代理方法,實(shí)際上都一樣)

原理:

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

  1. - (void)tableViewConstraints { 
  2.     [self.tableView mas_makeConstraints:^(MASConstraintMaker *make) { 
  3.         make.edges.equalTo(self.view); 
  4.     }]; 
  5.   
  6. - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 
  7.     return self.dataList.count
  8.   
  9. - (MasonryTableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 
  10.     MasonryTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:LXZTableViewCellIdentifier]; 
  11.     [cell reloadViewWithText:self.dataList[indexPath.row]]; 
  12.     return cell; 
  13.   
  14. // 需要注意的是,這個代理方法和直接返回當(dāng)前Cell高度的代理方法并不一樣。 
  15. // 這個代理方法會將當(dāng)前所有Cell的高度都預(yù)估出來,而不是只計算顯示的Cell,所以這種方式對性能消耗還是很大的。 
  16. // 所以通過設(shè)置estimatedRowHeight屬性的方式,和這種代理方法的方式,最后性能消耗都是一樣的。 
  17. - (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath { 
  18.     return 50.f; 
  19.   
  20. - (UITableView *)tableView { 
  21.     if (!_tableView) { 
  22.         _tableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain]; 
  23.         _tableView.delegate = self; 
  24.         _tableView.dataSource = self; 
  25.         // 設(shè)置tableView自動高度 
  26.         _tableView.rowHeight = UITableViewAutomaticDimension; 
  27.         [_tableView registerClass:[MasonryTableViewCell class] forCellReuseIdentifier:LXZTableViewCellIdentifier]; 
  28.         [self.view addSubview:_tableView]; 
  29.     } 
  30.     return _tableView; 

 UIScrollView自動布局

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

我這里就講一下兩種進(jìn)行UIScrollView自動布局的方案,并且會講一下自動布局的技巧,只要掌握技巧,布局其實(shí)很簡單。

布局小技巧:

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

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

提前設(shè)置contentSize

  1. // 提前設(shè)置好UIScrollView的contentSize,并設(shè)置UIScrollView自身的約束 
  2. self.scrollView.contentSize = CGSizeMake(1000, 1000); 
  3. [self.scrollView mas_makeConstraints:^(MASConstraintMaker *make) { 
  4.     make.edges.equalTo(self.view); 
  5. }]; 
  6.   
  7. // 雖然redView的get方法內(nèi)部已經(jīng)執(zhí)行過addSubview操作,但是UIView始終以最后一次添加的父視圖為準(zhǔn),也就是redView始終是在最后一次添加的父視圖上。 
  8. [self.scrollView addSubview:self.redView]; 
  9. [self.redView mas_makeConstraints:^(MASConstraintMaker *make) { 
  10.     make.left.top.equalTo(self.scrollView); 
  11.     make.width.height.mas_equalTo(200); 
  12. }]; 
  13.   
  14. [self.scrollView addSubview:self.blueView]; 
  15. [self.blueView mas_makeConstraints:^(MASConstraintMaker *make) { 
  16.     make.left.equalTo(self.redView.mas_right); 
  17.     make.top.equalTo(self.scrollView); 
  18.     make.width.height.equalTo(self.redView); 
  19. }]; 
  20.   
  21. [self.scrollView addSubview:self.greenView]; 
  22. [self.greenView mas_makeConstraints:^(MASConstraintMaker *make) { 
  23.     make.left.equalTo(self.scrollView); 
  24.     make.top.equalTo(self.redView.mas_bottom); 
  25.     make.width.height.equalTo(self.redView); 
  26. }]; 

 自動contentSize

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

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

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

因?yàn)閷IScrollView進(jìn)行addSubview操作的時候,本質(zhì)上是往其contentView上添加。也就是containerView的父視圖是contentView,通過containerView撐起contentView視圖的大小,以此來實(shí)現(xiàn)動態(tài)改變contentSize。 

  1. // 在進(jìn)行約束的時候,要對containerView的上下左右都添加和子視圖的約束,以便確認(rèn)containerView的邊界區(qū)域。 
  2. [self.scrollView mas_makeConstraints:^(MASConstraintMaker *make) { 
  3.     make.edges.equalTo(self.view); 
  4. }]; 
  5.   
  6. CGFloat padding = LXZViewPadding; 
  7. [self.containerView mas_makeConstraints:^(MASConstraintMaker *make) { 
  8.     make.edges.equalTo(self.scrollView).insets(UIEdgeInsetsMake(padding, padding, padding, padding)); 
  9. }]; 
  10.   
  11. [self.containerView addSubview:self.greenView]; 
  12. [self.greenView mas_makeConstraints:^(MASConstraintMaker *make) { 
  13.     make.top.left.equalTo(self.containerView).offset(padding); 
  14.     make.size.mas_equalTo(CGSizeMake(250, 250)); 
  15. }]; 
  16.   
  17. [self.containerView addSubview:self.redView]; 
  18. [self.redView mas_makeConstraints:^(MASConstraintMaker *make) { 
  19.     make.top.equalTo(self.containerView).offset(padding); 
  20.     make.left.equalTo(self.greenView.mas_right).offset(padding); 
  21.     make.size.equalTo(self.greenView); 
  22.     make.right.equalTo(self.containerView).offset(-padding); 
  23. }]; 
  24.   
  25. [self.containerView addSubview:self.yellowView]; 
  26. [self.yellowView mas_makeConstraints:^(MASConstraintMaker *make) { 
  27.     make.left.equalTo(self.containerView).offset(padding); 
  28.     make.top.equalTo(self.greenView.mas_bottom).offset(padding); 
  29.     make.size.equalTo(self.greenView); 
  30.     make.bottom.equalTo(self.containerView).offset(-padding); 
  31. }];  
責(zé)任編輯:龐桂玉 來源: iOS大全
相關(guān)推薦

2015-06-24 10:17:24

UI流式布局

2010-08-27 09:11:27

Python單元測試

2018-05-10 15:54:39

2022-04-27 08:17:07

OCMock單元測試集成

2010-05-28 08:52:18

SVN項(xiàng)目

2011-05-31 09:36:46

Android 布局屬性

2011-06-24 16:27:41

QML UI

2024-08-19 14:01:00

2023-10-30 09:18:28

CSSColumns布局

2021-04-25 06:12:19

Java內(nèi)存布局JVM

2012-08-22 10:37:07

Word 2013Office 2013

2010-08-16 16:27:42

DIV布局屬性

2012-08-23 10:07:47

Word 2013

2011-04-22 11:01:36

框架布局界面設(shè)計Android

2010-09-02 13:39:51

CSS

2015-11-05 11:20:45

cocoaios

2016-03-18 09:36:13

ios基礎(chǔ)框架

2012-06-01 11:10:07

iOS基本框架圖示

2011-10-10 09:11:09

Java

2010-08-30 13:46:09

MeeGoMeeGo Touch
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號

成人av在线电影| 超级白嫩亚洲国产第一| 男女激情视频一区| 欧美不卡视频一区发布| www.555国产精品免费| 一区二区精品伦理...| 国产精品久久影院| 国产伦精品一区二区三| 成人美女av在线直播| 欧美日韩一区二区三区69堂| 香蕉av在线播放| 六月婷婷色综合| 欧美大片欧美激情性色a∨久久| 精品黑人一区二区三区观看时间| 在线日韩影院| 韩国精品一区二区三区| 欧美xxxx在线观看| 综合一区中文字幕| 黄色av网站在线| 国产精品毛片| 欧美激情乱人伦一区| 国产精品成人无码专区| 成人在线啊v| 午夜久久久久久电影| 97超碰免费观看| av网站在线播放| 一本色道久久综合亚洲精品不卡| 欧美成人激情免费网| 久久久精品高清| 五月婷婷综合久久| 成人一区二区三区| 97自拍视频| 国产乱淫av片免费| 麻豆极品一区二区三区| 久久久久青草大香线综合精品| 久久国产一区二区三区| 波多野吉衣中文字幕| 欧美绝顶高潮抽搐喷水合集| 欧美日韩黄色大片| 国产 日韩 亚洲 欧美| 国产传媒在线播放| 国产精品久久久久天堂| 欧美亚洲免费高清在线观看| 波多野结衣视频在线看| 亚洲一区日韩| 2019中文在线观看| 欧美国产日韩在线观看成人| 忘忧草精品久久久久久久高清| 91 com成人网| 亚洲一区二区偷拍| 国产情侣一区二区三区| 欧美性猛交丰臀xxxxx网站| 日韩在线视频在线观看| 手机在线免费看av| 艳妇臀荡乳欲伦亚洲一区| 日本在线高清视频一区| 国产在线小视频| 中文字幕欧美国产| 一区二区三区我不卡| 欧美日韩成人免费观看| 午夜视频福利在线| 久久综合狠狠综合久久综合88| 激情久久av| 国产黄色片免费观看| 国产精品亚洲午夜一区二区三区| **亚洲第一综合导航网站| 亚洲精品国产一区二| 成人丝袜18视频在线观看| 国内一区在线| 青青青草原在线| 欧美激情在线看| 自拍另类欧美| 国产精品偷拍| 色综合激情久久| 97超碰人人爽| 国产精品45p| 亚洲人成网在线播放| 中文字幕第二区| 在线中文字幕第一区| 国外成人免费在线播放| 国产美女www| 国产精品自拍av| 久久天堂国产精品| 亚洲成人三级| 午夜精品福利久久久| 北条麻妃在线视频| 国产精品美女久久久久人| 亚洲第一中文字幕| 波多野结衣一二三四区| 欧美丝袜一区| 中文字幕日韩av| 国产无遮挡又黄又爽在线观看| 丝袜美腿亚洲一区二区图片| 91亚洲精品视频| 欧美色视频免费| 伊人夜夜躁av伊人久久| 少妇高清精品毛片在线视频| 精品国产三级| 国产亚洲欧美一区| 精品少妇一二三区| 久久精品免费观看| 精品视频在线观看| av网站在线免费看推荐| 91精品1区2区| av在线播放网址| 国产精品不卡| 国产成人亚洲综合91| 亚洲精品久久久久久动漫器材一区| 久久久久久久久久电影| www.av91| av日韩久久| 亚洲欧美在线一区二区| 国产精品自拍视频一区| 黄页视频在线91| 日本免费高清不卡| 岛国av免费在线观看| 91麻豆精品国产91久久久久| 最近中文字幕在线mv视频在线| 国产在线日韩| 国产一区二区香蕉| av在线首页| 色久优优欧美色久优优| 黄色av网址在线观看| 欧美va亚洲va日韩∨a综合色| 国产精品盗摄久久久| 性感美女福利视频| 亚洲国产aⅴ天堂久久| 三大队在线观看| 91精品高清| 成人福利网站在线观看| 国内三级在线观看| 日韩欧美国产中文字幕| 欧美双性人妖o0| 欧美日一区二区在线观看| 亚洲精品免费网站| 二区三区四区高清视频在线观看| 在线观看av不卡| 日韩av在线看免费观看| 国产欧美日本| 久久国产一区二区| 悠悠资源网亚洲青| 亚洲欧洲偷拍精品| 在线观看日本视频| 久久精品一区二区三区不卡| 久久无码高潮喷水| 精品久久网站| 国产精品色视频| 欧美性天天影视| 欧美一区二区成人6969| 日韩女优一区二区| 粉嫩av一区二区三区| 日韩黄色片在线| 精品精品精品| 国产ts一区二区| 国产日韩精品在线看| 欧美伊人久久久久久午夜久久久久| xxx在线播放| 麻豆精品一区二区三区| 国产精品美女在线播放| 精品久久亚洲| 国内成人精品视频| 欧美男男激情freegay| 91搞黄在线观看| 精品国产大片大片大片| 国产一区二区精品久久99| 精品人妻人人做人人爽| 欧美a一欧美| 国产97免费视| 超碰免费在线播放| 亚洲成人精品视频在线观看| 中文字幕亚洲乱码熟女1区2区| 亚洲国产精品国自产拍av| 在线看免费毛片| 亚洲第一黄网| 日本亚洲导航| 日韩精品久久久久久久软件91| 668精品在线视频| www.亚洲.com| 日韩精品最新网址| 国产高清中文字幕| 亚洲欧美日韩在线| 7788色淫网站小说| 久久99精品久久久久婷婷| 日本人体一区二区| 日韩电影免费在线观看| 国产高清一区视频| 免费观看成人性生生活片 | 欧美在线亚洲| 久久天天狠狠| 日本精品在线播放| 热99久久精品| 污视频在线看网站| 亚洲网址你懂得| 亚洲国产成人在线观看| 欧美色手机在线观看| 国产真实夫妇交换视频| 亚洲国产精品高清| 中文在线永久免费观看| 麻豆国产精品777777在线| 亚洲 欧美 综合 另类 中字| 日韩在线观看电影完整版高清免费悬疑悬疑 | 成人性视频网站| 性chinese极品按摩| 99在线精品视频在线观看| 福利网在线观看| 国内精品久久久久久99蜜桃| 成人综合电影| 中文字幕成人| 国产精品久久久久77777| 18video性欧美19sex高清| 久久久999成人| 成人免费视频| 亚洲美女av电影| 蜜桃av噜噜一区二区三区麻豆| 欧美日韩高清在线| 精人妻无码一区二区三区| 午夜精品aaa| 久久精品人妻一区二区三区| 亚洲激情在线激情| 91制片厂在线| 中文字幕在线观看一区| www.日本高清视频| 国产色爱av资源综合区| wwwwxxxx国产| 91亚洲精品乱码久久久久久蜜桃| 91亚洲一线产区二线产区 | 欧美日韩国产综合草草| 欧美成人一区二区三区四区| 欧美日韩免费观看中文| 四虎永久在线精品| 亚洲国产一区二区a毛片| 麻豆亚洲av熟女国产一区二 | 亚洲欧美日韩不卡| 99视频精品全部免费在线视频| 日韩影视精品| 欧美精选一区二区三区| 日韩片电影在线免费观看| 精品大片一区二区| 欧美污视频久久久| 精品欧美久久| 亚洲图片欧洲图片日韩av| 成人一二三区| 一区二区视频在线观看| 一区二区三区四区电影| 色中文字幕在线观看| 中文字幕一区二区三区在线视频| 成人在线观看www| 欧美成人精品| 欧美在线一区视频| 亚洲一区免费| 成人性视频欧美一区二区三区| 日韩精品成人一区二区在线| 国产视频一区二区视频| 久久精品国产免费看久久精品| 911av视频| 国产成人免费高清| 中文字幕 亚洲一区| 国产日韩av一区| 亚洲熟女少妇一区二区| 一区二区成人在线| 国产欧美一区二区三区在线看蜜臂| 色悠久久久久综合欧美99| 中文天堂在线资源| 日韩一级二级三级| 神马午夜精品95| 亚洲网址你懂得| 成人免费在线| 91精品国产91久久久久| jizz欧美| 99久久伊人精品影院| 小说区图片区色综合区| 亚洲一二三区精品| 亚洲午夜极品| 无码日韩人妻精品久久蜜桃| 国产一区激情在线| 亚洲国产精品自拍视频| 中文字幕av不卡| 毛片a片免费观看| 一本到一区二区三区| 国产精品视频一二区| 亚洲国产另类久久精品| 东凛在线观看| 久久频这里精品99香蕉| 欧洲一级精品| 国产高清一区视频| 久久中文字幕av| 日韩国产欧美亚洲| 精品在线一区二区三区| 黄色av网址在线观看| 日韩毛片精品高清免费| 狠狠人妻久久久久久| 欧美一区二区三区在线看| 日本大片在线观看| 久久综合伊人77777| 欧美成人精品三级网站| 91文字幕巨乱亚洲香蕉| 成人在线免费视频观看| 国产精品裸体瑜伽视频| 国产乱码精品一区二区三区忘忧草| 成人免费网站黄| 亚洲一线二线三线视频| 亚洲专区第一页| 亚洲三级av在线| av在线资源| 91精品国产综合久久久久久丝袜| 国产综合在线观看| 久久精品国产欧美激情| 波多视频一区| 国产欧美亚洲日本| 亚洲精品久久| 艹b视频在线观看| 国产情人综合久久777777| 国产福利久久久| 在线91免费看| av播放在线观看| 欧美一区深夜视频| 福利片一区二区| 男人天堂网站在线| 久久成人精品无人区| 国产毛片欧美毛片久久久| 欧美视频在线观看免费| 91久久久久久久久久久久久| 中文字幕久久精品一区二区| 欧美日韩在线免费观看视频| 秋霞影院一区二区| 中文字幕网站在线观看| 色综合久久综合中文综合网| 少妇一区二区三区四区| 久久久久久久久久久国产| 免费精品一区| 欧美性受xxxx黑人猛交88| 久久电影国产免费久久电影| 国产精品18在线| 欧美色倩网站大全免费| 国产粉嫩一区二区三区在线观看| 国产99久久精品一区二区| 亚洲另类av| 国产日韩一区二区在线| wwww国产精品欧美| 日本一区二区三区精品| 日韩电影中文字幕av| 涩涩网在线视频| 免费看污久久久| 老牛影视一区二区三区| av男人的天堂av| 欧美日韩精品一区视频| 亚洲s色大片| 亚洲伊人一本大道中文字幕| 欧美精品三区| 又黄又爽的网站| 日韩欧美国产激情| porn亚洲| 亚洲va男人天堂| 欧美日本三区| 中国一级特黄录像播放| 岛国av一区二区三区| 国产三级电影在线| 91日本视频在线| 亚洲电影在线| 日韩在线免费观看av| 欧美日韩一区国产| 2021国产在线| 精品中文字幕人| 午夜一区在线| 我要看一级黄色录像| 欧美成人伊人久久综合网| 午夜影院在线播放| 亚洲精品成人久久久998| 国产一级精品在线| 青青操免费在线视频| 亚洲天堂av在线播放| 国色天香久久精品国产一区| 精品无码国产一区二区三区av| 26uuu亚洲综合色欧美 | 欧美日韩大陆在线| 污污的网站在线免费观看| 久久人人九九| 国产一区二区三区在线观看免费视频 | 91福利在线观看| 国产精品久久久久久福利| 国产精品一区二| 蜜臀av在线播放一区二区三区| a级片在线观看免费| 亚洲人成在线观看网站高清| 图片一区二区| 免费日韩视频在线观看| 亚洲精品中文字幕乱码三区 | 久久伊人精品一区二区三区| 老汉色老汉首页av亚洲| 最新天堂在线视频| 黄色精品在线看| 黄页视频在线播放| 免费看污久久久| 成人免费毛片高清视频| 亚洲在线免费观看视频| 2019中文字幕在线观看| 一个色综合网| 懂色av粉嫩av浪潮av| 亚洲国产欧美精品| 麻豆视频久久|