masonry使用技巧

masonry git地址:https://github.com/SnapKit/Masonry

本文主要會講到masonry英文文檔(見上面的git地址)中提及到的使用說明,以及個人使用過程中的一些經(jīng)驗,僅適用一些剛使用masonry的新手,大牛可以忽略,當然也可以進來指點。

一、常用的屬性與常量

1. MASViewAttribute 以對應的系統(tǒng)類型

MASViewAttribute NSLayoutAttribute
view.mas_left NSLayoutAttributeLeft
view.mas_right NSLayoutAttributeRight
view.mas_top NSLayoutAttributeTop
view.mas_bottom NSLayoutAttributeBottom
view.mas_leading NSLayoutAttributeLeading
view.mas_trailing NSLayoutAttributeTrailing
view.mas_width NSLayoutAttributeWidth
view.mas_height NSLayoutAttributeHeight
view.mas_centerX NSLayoutAttributeCenterX
view.mas_centerY NSLayoutAttributeCenterY
view.mas_baseline NSLayoutAttributeBaseline

2.UIView

先來一波最為常用的使用方法,大家可以看一下大致語法,下面會細講使用

//.分別設置各個相對邊距(superview為view的父類視圖,下同)
make.left.mas_equalTo(superView.mas_left).mas_offset(10);
make.right.mas_equalTo(superView.mas_right).mas_offset(-10);
make.top.mas_equalTo(superView.mas_top).mas_offset(10);
make.bottom.mas_equalTo(superView.mas_bottom).offset(-10);

//直接連接使用left大于等于每個值
make.left.mas_greaterThanOrEqualTo(10);

//設置寬和高
make.width.mas_equalTo(60);
make.height.mas_equalTo(60);

//.設置center和款高比
make.center.mas_equalTo(superView);
make.width.mas_equalTo(superView).multipliedBy(1.00/3);
make.height.mas_equalTo(superView).multipliedBy(0.25);

//.關于約束優(yōu)先級,此處要注意約束沖突的問題,統(tǒng)一約束優(yōu)先級大的生效
make.left.mas_equalTo(100);
make.left.mas_equalTo(view.superview.mas_left).offset(10);
make.left.mas_equalTo(20).priority(700);
make.left.mas_equalTo(40).priorityHigh();
make.left.mas_equalTo(60).priorityMedium();
make.left.mas_equalTo(80).priorityLow();

//.如果你想讓view的(x坐標)左邊大于等于label的左邊,以下兩個約束的寫法效果一樣
 make.left.greaterThanOrEqualTo(label);
 make.left.greaterThanOrEqualTo(label.mas_left);

注:約束的鏈式寫法中,不包含其他相對的view時,默認為其superview,即make.left.mas_equalTo(100);等價于make.left.mas_equalTo(view.superview.mas_left).offset(10);make.left.mas_equalTo(view.superview).offset(10);

3. NSNumber

自動布局允許使用常量去設置寬或高,如果你想通過一個數(shù)字設置一個view的最小和最大的width,可以用equality blocks,如下:

//width >= 200 && width <= 400

make.width.greaterThanOrEqualTo(@200);

make.width.lessThanOrEqualTo(@400)

然而自動布局不允許對齊屬性的約束(如:left,right,centerY等)設置為常量值,你可以使用NSNumber來設置相對于父類view這些約束屬性,如:

// creates view.left = view.superview.left + 10
make.left.lessThanOrEqualTo(@10)

如果你不想使用NSNumber來設置,也可以用如下結構來創(chuàng)建你的約束,如:


make.top.mas_equalTo(42);

make.height.mas_equalTo(20);

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

make.edges.mas_equalTo(UIEdgeInsetsMake(10, 0, 10, 0));

make.left.mas_equalTo(view).mas_offset(UIEdgeInsetsMake(10, 0, 10, 0));

以上用法默認添加mas_前綴,如果你不想添加此前綴,但還想使用常量值設置約束,需要在導入Masonry頭文件前,設置宏定義MAS_SHORTHAND_GLOBALS,至于為什么,去masonry代碼中搜索一下MAS_SHORTHAND_GLOBALS便知。

4. NSArray

用數(shù)組添加集中不同類的約束,如:

make.height.equalTo(@[view1.mas_height, view2.mas_height]);

make.height.equalTo(@[view1, view2]);

make.left.equalTo(@[view1, @100, view3.right]);

二、約束的優(yōu)先級屬性

  • .priority允許你設置一個非常準確的的約束優(yōu)先級(0-1000)

  • .priorityHigh 相當于系統(tǒng)的 UILayoutPriorityDefaultHigh

  • .priorityMedium 介于 high and low之間的優(yōu)先級

  • .priorityLow 相當于系統(tǒng)的 UILayoutPriorityDefaultLow

注:默認通過mas_make添加的約束不設置優(yōu)先級時,默認都是最高(1000)

優(yōu)先級屬性可以放在約束鏈的末端使用,如:

make.left.greaterThanOrEqualTo(label.mas_left).with.priorityLow();
make.top.equalTo(label.mas_top).with.priority(600);

三、更加便利的約束方法

Masonry提供了一些便利的方法供我們同時創(chuàng)建多個不同的約束,他們被稱為MASCompositeConstraints,如:

edges

// 使一個view的top, left, bottom, right 等于view2的

make.edges.equalTo(view2);

//相對于superviewde上左下右邊距分別為5,10,15,20

make.edges.equalTo(superview).insets(UIEdgeInsetsMake(5, 10, 15, 20))

size

// 使得寬度和高度大于等于 titleLabel

make.size.greaterThanOrEqualTo(titleLabel)

// 相對于superview寬度大100,高度小50

make.size.equalTo(superview).sizeOffset(CGSizeMake(100, -50))

center

//中心與button1對齊

make.center.equalTo(button1)

//水平方向中心相對向左偏移5,豎直方向中心向下偏移10

make.center.equalTo(superview).centerOffset(CGPointMake(-5, 10))

你可以在約束鏈里添加相應的view來增加代碼的可讀性:

// 除了top,所有的邊界與superview對齊

make.left.right.and.bottom.equalTo(superview);

make.top.equalTo(otherView);

四、關于如何修改約束

有時候,你為了實現(xiàn)動畫或者移除替換一些約束時,你需要去修改一些已經(jīng)存在的約束,Masonry提供了一些不同的方法去更新約束,你也可以將多個約束存在數(shù)組里

1. References

你可以持有某個特定的約束,讓其成為成員變量或者屬性
//設置為公共或私接口

@property (nonatomic, strong) MASConstraint *topConstraint;

...

// 添加約束

[view1 mas_makeConstraints:^(MASConstraintMaker *make) {

self.topConstraint = make.top.equalTo(superview.mas_top).with.offset(padding.top);

make.left.equalTo(superview.mas_left).with.offset(padding.left);

}];

...

// 然后可以調(diào)用
//該約束移除
[self.topConstraint uninstall];
//重新設置value,最常用
self.topConstraint.mas_equalTo(20);
//該約束失效
[self.topConstraint deactivate];
//該約束生效
[self.topConstraint activate];

2. mas_updateConstraints

如果你只是想更新一下view對應的約束,可以使用 mas_updateConstraints 方法代替 mas_makeConstraints方法
//這是蘋果推薦的添加或者更新約束的地方

// 在響應setNeedsUpdateConstraints方法時,這個方法會被調(diào)用多次

// 此方法會被UIKit內(nèi)部調(diào)用,或者在你觸發(fā)約束更新時調(diào)用

- (void)updateConstraints {

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

make.center.equalTo(self);

make.width.equalTo(@(self.buttonSize.width)).priorityLow();

make.height.equalTo(@(self.buttonSize.height)).priorityLow();

make.width.lessThanOrEqualTo(self);

make.height.lessThanOrEqualTo(self);

}];

//調(diào)用super
[super updateConstraints];

}

3. mas_remakeConstraints

mas_updateConstraints只是去更新一些約束,然而有些時候修改一些約束值是沒用的,這時候mas_remakeConstraints就可以派上用場了

mas_remakeConstraints某些程度相似于mas_updateConstraints,但不同于mas_updateConstraints去更新約束值,他會移除之前的view的所有約束,然后再去添加約束

- (void)changeButtonPosition {

      [self.button mas_remakeConstraints:^(MASConstraintMaker *make) {

      make.size.equalTo(self.buttonSize);

     if (topLeft) {

          make.top.and.left.offset(10);

     } else {

     make.bottom.and.right.offset(-10); 

   }

  }];

五、在哪創(chuàng)建我的約束

貼一個官方說明的例子:

@implementation DIYCustomView

- (id)init {

self = [super init];

if (!self) return nil;

// --- Create your views here ---

self.button = [[UIButton alloc] init];

return self;

}

// tell UIKit that you are using AutoLayout

+ (BOOL)requiresConstraintBasedLayout {

return YES;

}

// this is Apple's recommended place for adding/updating constraints

- (void)updateConstraints {

// --- remake/update constraints here

[self.button remakeConstraints:^(MASConstraintMaker *make) {

make.width.equalTo(@(self.buttonSize.width));

make.height.equalTo(@(self.buttonSize.height));

}];

//according to apple super should be called at end of method

[super updateConstraints];

}

- (void)didTapButton:(UIButton *)button {

// --- Do your changes ie change variables that affect your layout etc ---

self.buttonSize = CGSize(200, 200);

// tell constraints they need updating

[self setNeedsUpdateConstraints];

}

六、Layout必備知識

AutoLayout關于更新的幾個方法的區(qū)別

  • setNeedsLayout:告知頁面需要更新,但是不會立刻開始更新。執(zhí)行后會立刻調(diào)用layoutSubviews。

  • layoutIfNeeded:告知頁面布局立刻更新。所以一般都會和setNeedsLayout一起使用。如果希望立刻生成新的frame需要調(diào)用此方法,利用這點一般布局動畫可以在更新布局后直接使用這個方法讓動畫生效。

  • layoutSubviews:系統(tǒng)重寫布局

  • setNeedsUpdateConstraints:告知需要更新約束,但是不會立刻開始

  • updateConstraintsIfNeeded:告知立刻更新約束

  • updateConstraints:系統(tǒng)更新約束

七、使用tips

  • 給view添加約束時,必須已經(jīng)添加到其superview上面
  • 不需要設置view.translatesAutoresizingMaskIntoConstraints = NO;,masonry內(nèi)部已經(jīng)幫我設置過了
  • 手寫布局時,合理使用約束,盡量約束沖突問題
  • 因為iOS中原點在左上角所以注意使用offset時注意right和bottom用負數(shù)

推薦兩個大牛寫的關于Masonry源碼解析的博客

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

  • 一、前言 關于蘋果的布局一直是我比較糾結的問題,是寫代碼來控制布局,還是使用storyboard來控制布局呢?以前...
    iplaycodex閱讀 2,743評論 0 1
  • Masonry是iOS在控件布局中經(jīng)常使用的一個輕量級框架,Masonry讓NSLayoutConstraint使...
    丘比沙拉閱讀 3,237評論 2 19
  • Masonry是iOS在控件布局中經(jīng)常使用的一個輕量級框架,Masonry讓NSLayoutConstraint使...
    愛敲代碼的果果閱讀 2,000評論 0 2
  • Autolayout就像一個知情達理,善解人意的好姑娘,可惜長相有點不堪入目,所以追求者寥寥無幾。所幸遇到了化妝大...
    小笨狼閱讀 24,219評論 28 227
  • 今天又多看到了一篇夜行日記。 也許是因為他比較成熟,所以反而很多事都藏著放在心里。 當他還在發(fā)夜行日記的時候,我會...
    安褚閱讀 337評論 0 0

友情鏈接更多精彩內(nèi)容