iOS Autolayout之Masonry解讀

原文地址: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的關鍵就是如何設置約束,讓空間滿足位置,尺寸這兩個必要條件
    • 還有就是,當一個控件的約束已經能夠滿足上述兩個條件了,就不要再添加多餘的約束了,很容易會照成約束衝突
    • 除非你想設置其他優先級的約束
    • 優先級會在例子中說明其用處

      例子講解

  • 由於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,你就想着是用英語在造句就行了,哈哈
    • 還有一點,andwith其實就是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的使用語法或者是對約束的思想還有什麼不理解,希望您可以不吝惜的提出來,我希望能把文章做得更通俗易懂,更深刻!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章