原文地址:http://www.jianshu.com/p/10a250cc5018
Masonry
- Masonry是公認非常簡潔優美的一款Autolayout框架
- 我推薦大家重點學習這個框架
- 我會把Autolayout的思維融合這個框架一起講解
Masonry的使用
- 想要使用第三方Masonry要麼要去GitHub上下載原代碼下來拖進項目中,要麼就直接使用cocoapods,pod search Masonry,下載最新版
- cocoapods的使用不是本文討論的範圍,大家可以百度一下哈,安裝非常簡單
Masonry的講解
- 因爲之前的一篇關於VFL的文章我自我感覺寫的不是太好,其實主要原因是VFL的約束創建非常宏觀,如果既要照顧語法講解,又要照顧約束理解,反而介紹會使文章增加很多口水話,長而乏味
- Masonry的約束添加思維其實與蘋果原API的添加思維是相同的,只是Masonry語法更簡潔,代碼更優美
- 在這裏,爲了融合Autolayout的思想,我依然要說下面幾點
- Autolayout所倡導的兩個核心詞是
約束
,參照
- 而我認爲,Autolayout其實核心思想還是爲了設置
frame
- 無論我們如何添加
約束
,最終還是爲了確定其位置
與尺寸
- 所以,Autolayout的關鍵就是如何設置約束,讓空間滿足
位置
,尺寸
這兩個必要條件 - 還有就是,當一個控件的約束已經能夠滿足上述兩個條件了,就不要再添加多餘的約束了,很容易會照成約束衝突
- 除非你想設置其他
優先級
的約束 優先級
會在例子中說明其用處例子講解
- Autolayout所倡導的兩個核心詞是
- 由於Masonry是重點推薦的,我會分別用三個例子來講訴它
第一個例子
- 這個例子很簡單,僅僅是爲了向大家介紹Masonry的語法
- 比起文字闡述需求,我不如直接上圖讓大家看得更直接明白
- 實現後的效果是這樣的
- ok,接下來看看怎麼用代碼去實現這個效果
-
先添加四個View
UIView *redView = [[UIView alloc]init]; redView.backgroundColor = [UIColor redColor]; [self.view addSubview:redView]; UIView *blueView = [[UIView alloc]init]; blueView.backgroundColor = [UIColor blueColor]; [self.view addSubview:blueView]; UIView *yellow = [[UIView alloc]init]; yellow.backgroundColor = [UIColor yellowColor]; [self.view addSubview:yellow]; UIView *green = [[UIView alloc]init]; green.backgroundColor = [UIColor greenColor]; [self.view addSubview:green];
- 創建添加紅色View的約束
- 先來看看語法
- Masonry的語法可讀性非常強
- 所以我不會在這裏死板的一個單詞一個單詞的介紹
- 大家在寫的時候完全就可以像寫句子一樣,並且Masonry添加約束都是
mas_makeConstraints
這個方法 - 只需要在塊中寫上想好的約束
- 比如下面的第一個約束
- 翻譯過來就是
使左邊等於self.view的左邊,間距爲0
- 而在塊中主語就是調用者,這裏也就是redView
- 所以使用Masonry,你就想着是用英語在造句就行了,哈哈
- 還有一點,
and
與with
其實就是get調用者本身,裏面僅僅是return self
[redView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(self.view.mas_left).offset(0);//使左邊等於self.view的左邊,間距爲0
make.top.equalTo(self.view.mas_top).offset(0);//使頂部與self.view的間距爲0
make.width.equalTo(self.view.mas_width).multipliedBy(0.5);//設置寬度爲self.view的一半,multipliedBy是倍數的意思,也就是,使寬度等於self.view寬度的0.5倍
make.height.equalTo(self.view.mas_height).multipliedBy(0.5);//設置高度爲self.view高度的一半
}];
- 上面我已經添加了redView的約束,它已經擁有了寬和高,還有水平方向和垂直方向的位置,也就是frame中的x,y,width,height,都有了
- 所以redView的約束就添加完成了,無需再添加過多的約束
- 其他的view將要以它爲
錨點
,來添加約束,確定自身的位置
與尺寸
- 接下來設置blueView的約束
- 大家在看下面代碼之前可以自己思考,按照
圖1
中的blueView的效果,我們應當怎樣添加約束呢? - 很明顯,只需要與紅色等寬高,並且與紅色左間距爲0,頂部對齊,就可以了
[blueView mas_makeConstraints:^(MASConstraintMaker *make) {
make.width.and.height.equalTo(redView);//使寬高等於redView
make.top.equalTo(redView.mas_top);//與redView頂部對齊
make.leading.equalTo(redView.mas_right);//與redView的間距爲0
}];
- 剩下的兩個View的約束我就不過多的闡述了,大家可以自己先想一下怎麼添加約束,再來看我代碼是怎麼實現的
- 當然,很可能你的想法和我的實現不一樣,這是很正常的,約束的實現方法有太多了
- 但是萬變不離其宗!一定得保證最終設置完畢後,所有的控件都擁有了
位置
與尺寸
[yellow mas_makeConstraints:^(MASConstraintMaker *make) {
make.leading.equalTo(redView);//與redView左對齊
make.top.equalTo(redView.mas_bottom);//與redView底部間距爲0
make.width.and.height.equalTo(redView);//與redView寬高相等
}];
[green mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(yellow.mas_right);//與yellow右邊間距爲0
make.top.equalTo(blueView.mas_bottom);//與blueView底部間距爲0
make.width.and.height.equalTo(redView);//與redView等寬高
}];
第二個例子
- 這個例子我希望大家能對約束的理念有個更深的理解
- 因爲我一路寫下來,一直用的都是固定
尺寸
的例子,或者是固定位置
的例子,我怕誤導大家認爲Autolayout是非常死板的,必須把每個控件的約束添加到滿足位置
與尺寸
,再去添加其他控件的約束,這樣纔不會出錯 - 其實不是這樣的,的確,在所有控件添加完約束後,得擁有自己的
位置
與尺寸
,但是有時這兩個必須條件可以利用相對
來滿足 - 接下來我就用例子來解釋吧
- 先讓大家看一下效果圖
- 正如大家在圖片所看到的,我希望兩個等寬高的紅色方塊能夠在屏幕旋轉的時候,間距等比例縮放,它們的相對位置是固定的,絕對位置隨着屏幕的寬改變而改變
- 其他三個灰色的方塊,它們的寬是不確定,這就是我想要和大家說的
相對
概念 - 我並沒有固定死灰色方塊的寬度,只要求它們與紅色方塊的間距爲0,並且灰色方塊的寬度相等
- 但是紅色方塊的寬度是固定的,灰色方塊就會互相相等的寬度,填充着紅色方塊間的空隙
- 接下來看看代碼是怎麼實現的吧
- 添加View的代碼我就不上了,直接看添加約束的代碼
//代碼中View的順序與圖中從左到右的View的順序一致
//例子中,唯一不確定的就是灰色View的寬度,我們先把確定的約束給一個一個的添加上來
//灰1左間距、高度、垂直位置(因爲和紅1底部對齊)是確定的,添加約束
[gray1 mas_makeConstraints:^(MASConstraintMaker *make) {
make.height.mas_equalTo(20);
make.leading.equalTo(self.view.mas_leading).offset(0);
make.bottom.equalTo(red1.mas_bottom);
}];
//紅1,寬高、左間距、底間距是確定的,添加約束
[red1 mas_makeConstraints:^(MASConstraintMaker *make) {
make.width.mas_equalTo(100);
make.height.mas_equalTo(50);
make.left.equalTo(gray1.mas_right);
make.bottom.equalTo(self.view.mas_bottom).offset(-50);
}];
//灰2,左間距、高度、垂直位置是確定的,寬度要與灰1一致,是爲了能均勻填充,添加約束
[gray2 mas_makeConstraints:^(MASConstraintMaker *make) {
make.height.and.width.equalTo(gray1);
make.leading.equalTo(red1.mas_right);
make.bottom.equalTo(red1.mas_bottom);
}];
//紅2,寬高、左間距、底間距是確定的,添加約束
[red2 mas_makeConstraints:^(MASConstraintMaker *make) {
make.height.and.width.equalTo(red1);
make.leading.equalTo(gray2.mas_right);
make.bottom.equalTo(red1.mas_bottom);
}];
//灰3,左間距、右間距、高度、垂直位置是確定的,添加約束
[gray3 mas_makeConstraints:^(MASConstraintMaker *make) {
make.height.and.width.equalTo(gray1);
make.leading.equalTo(red2.mas_right);
make.trailing.equalTo(self.view.mas_right);
make.bottom.equalTo(red1.mas_bottom);
}];
- 大家看了上面的講解後,會發現三個灰色方塊都沒有設置固定的寬
- 但是它們三個都等寬,紅色方塊又是固定的,那麼在這5個View間距都爲0的情況下,灰色方塊不就會去擠壓紅色方塊,直到灰色方塊寬度相等,那麼紅色方塊也處在了應有的位置麼
- 這就是我想說的
相對
,紅色方塊寬度是固定的,那麼水平方向上的間距就需要剩下的三個灰色方塊去填充,當界面橫屏時,三個灰色方塊爲了相對
自身寬度要相同,相對
紅色邊界,self.view邊界,間距保持爲0,那麼就得犧牲自身寬度的穩定,去維持這些相對
的約束 - 希望我這些話能幫助大家更深刻的理解約束,更多的東西需要大家去做項目慢慢體會
第三個例子
- 最後這個例子是老例子了,我想給大家看看其實Masonry做動畫也和其他的Autolayout方法一樣,但是添加約束的代碼卻非常的少,可以和我之前的另一篇文章比較一下
- 裏面的約束我就不講解了,看了上面的代碼,下面的約束對你來說肯定是小菜一碟
- 約束代碼
UIView *redView = [[UIView alloc]init];
redView.backgroundColor = [UIColor redColor];
[self.view addSubview:redView];
UIView *greenView = [[UIView alloc]init];
greenView.backgroundColor = [UIColor greenColor];
[self.view addSubview:greenView];
UIView *blueView = [[UIView alloc]init];
blueView.backgroundColor = [UIColor blueColor];
[self.view addSubview:blueView];
[redView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(self.view.mas_left).offset(20);
make.bottom.equalTo(self.view.mas_bottom).offset(-20);
make.width.equalTo(self.view.mas_width).multipliedBy(0.2);
make.height.equalTo(self.view.mas_height).multipliedBy(0.2);
}];
[greenView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(redView.mas_right).offset(20);
make.bottom.equalTo(self.view.mas_bottom).offset(-20);
make.width.equalTo(self.view.mas_width).multipliedBy(0.2);
make.height.equalTo(self.view.mas_height).multipliedBy(0.2);
}];
[blueView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(greenView.mas_right).offset(20);
make.bottom.equalTo(self.view.mas_bottom).offset(-20);
make.width.equalTo(self.view.mas_width).multipliedBy(0.2);
make.height.equalTo(self.view.mas_height).multipliedBy(0.2);
make.left.equalTo(redView.mas_right).offset(20).priority(250);
}];
- 動畫代碼
[self.greenView removeFromSuperview];
[UIView animateWithDuration:1.0f animations:^{
[self.view layoutIfNeeded];
}];
- 好了,Masonry就爲大家講解到這裏,如果對Masonry的使用語法或者是對約束的思想還有什麼不理解,希望您可以不吝惜的提出來,我希望能把文章做得更通俗易懂,更深刻!