你好,歡迎來到IOS教程網

 Ios教程網 >> IOS編程開發 >> IOS開發綜合 >> iOS開發 -- Autolayout第三方庫Masonry的入門與實踐

iOS開發 -- Autolayout第三方庫Masonry的入門與實踐

編輯:IOS開發綜合

在如今的iOS開發中,Autolayout已經是不得不使用了,而且是我們主動的去擁抱Autolayout。使用Autolayout最普遍的方式就是在xib或者storyboard中可視化的添加各種約束,這也是Autolayout入門需要掌握的。對於比較簡單的App開發,可能使用可視化Autolayout也就足夠了。但是如果UI布局稍微復雜多變一點,那麼就不得不使用代碼了。對於iOS原生的代碼自動布局,真的是過於繁瑣。所以這裡就要來介紹目前廣泛使用的第三方庫Masonry的使用,入門非常的方便簡單。也是一位合格的iOS開發者需要掌握的。博客案例代碼上傳至 https://github.com/chenyufeng1991/MasonryLearnDemo。

(1)使用Cocoapods導入Masonry。Podfile文件如下:

 

platform:ios,'8.0'
pod 'Masonry'

(2)先對Masonry中的內容做一個簡單的介紹:

 

Masonry中有三種添加約束的方法:

- (NSArray *)mas_makeConstraint:(void(^)(MASConstraintMaker *))block;

- (NSArray *)mas_updateConstraint:(void(^)(MASConstraintMaker *))block;

- (NSArray *)mas_remakeConstraint:(void(^)(MASConstraintMaker *))block;

mas_makeConstraint:只負責新增約束,初次設置約束使用;

mas_updateConstraint:更新block中出現的約束,如果找不到該約束,會新增約束。

mas_remakeConstraint:清除之前的所有約束,僅保留最新的約束。

 

(3)equalTo和mas_equalTo的區別

其實mas_equalTo是一個宏,源碼中是這樣定義的:

 

 #define mas_equalTo(...)                 equalTo(MASBoxValue((__VA_ARGS__)))
 #define mas_greaterThanOrEqualTo(...)    greaterThanOrEqualTo(MASBoxValue((__VA_ARGS__)))
 #define mas_lessThanOrEqualTo(...)       lessThanOrEqualTo(MASBoxValue((__VA_ARGS__)))

 #define mas_offset(...)                  valueOffset(MASBoxValue((__VA_ARGS__)))

 

 

同時,這裡涉及到兩個簡便寫法,Masonry提供了不加mas_前綴的方法,只需要定義兩個宏:

MAS_SHORTHAND宏:定義了MAS_SHORTHAND宏之後,就可以使用UIView,NSArray中不帶mas_前綴的makeConstraint,updateConstraint,remakeConstraint方法,以及UIView中不帶mas_前綴的Attribute。

MAS_SHORTHAND_GLOBALS:直接對equalTo傳入基礎類型,Masonry自動轉化為NSValue對象。

 

(4)比例系數與常數系數

multipliedBy(0.5)可以用來設置比例系數。

Masonry有四種設置Constant的方法:

 

- (MASConstraint * (^)(MASEdgeInsets insets))insets;
- (MASConstraint * (^)(CGSize offset))sizeOffset;
- (MASConstraint * (^)(CGPoint offset))centerOffset;
- (MASConstraint * (^)(CGFloat offset))offset;
insets方法可以同時設置top,left,bottom,right,接收MASEdgeInsets類型,也就是UiEdgeInsets類型,使用UIEdgeInetMake方法設置。

 

sizeOffset方法設置width,height,接收CGSize類型,使用CGSizeMake方法設置。

centerOffset方法設置centerX(X軸中心),centerY(Y軸中心)。

offset方法可以設置所有的偏移常量。
 

(5)對於一個約束,實際表示的是不等或者相等關系:

aView.Leading = 1.0 * bView.Trailing + 10;

其中:

aView :Item1;

Leading:Attribute1;

= : Relationship;

1.0 :Multiplier

bView:Item2;

Trailing :Attribute2;

10 :Constant;

 

(6)MASConstraintMaker提供了22種Attribute類型:

 

 //第一類
 @property (nonatomic, strong, readonly) MASConstraint *left;
 @property (nonatomic, strong, readonly) MASConstraint *top;
 @property (nonatomic, strong, readonly) MASConstraint *right;
 @property (nonatomic, strong, readonly) MASConstraint *bottom;
 @property (nonatomic, strong, readonly) MASConstraint *leading;
 @property (nonatomic, strong, readonly) MASConstraint *trailing;
 @property (nonatomic, strong, readonly) MASConstraint *width;
 @property (nonatomic, strong, readonly) MASConstraint *height;
 @property (nonatomic, strong, readonly) MASConstraint *centerX;
 @property (nonatomic, strong, readonly) MASConstraint *centerY;
 @property (nonatomic, strong, readonly) MASConstraint *baseline;

 //第二類
 @property (nonatomic, strong, readonly) MASConstraint *leftMargin;
 @property (nonatomic, strong, readonly) MASConstraint *rightMargin;
 @property (nonatomic, strong, readonly) MASConstraint *topMargin;
 @property (nonatomic, strong, readonly) MASConstraint *bottomMargin;
 @property (nonatomic, strong, readonly) MASConstraint *leadingMargin;
 @property (nonatomic, strong, readonly) MASConstraint *trailingMargin;
 @property (nonatomic, strong, readonly) MASConstraint *centerXWithinMargins;
 @property (nonatomic, strong, readonly) MASConstraint *centerYWithinMargins;
 
 //第三類
 @property (nonatomic, strong, readonly) MASConstraint *edges;
 @property (nonatomic, strong, readonly) MASConstraint *size;
 @property (nonatomic, strong, readonly) MASConstraint *center;

第一類是基本屬性,向下支持到iOS6,用的比較多。

 

第二類是邊緣相關屬性,向下支持到iOS8,由於版本要求比較高,所以用的比較少。

第三類是復合屬性,edges(top,left,right,bottom),size(width,height),center(centerX,centerY).

 

(7)擴展UIView中的Attribute:

 

 @property (nonatomic, strong, readonly) MASViewAttribute *mas_left;
 @property (nonatomic, strong, readonly) MASViewAttribute *mas_top;
 @property (nonatomic, strong, readonly) MASViewAttribute *mas_right;
 @property (nonatomic, strong, readonly) MASViewAttribute *mas_bottom;
 @property (nonatomic, strong, readonly) MASViewAttribute *mas_leading;
 @property (nonatomic, strong, readonly) MASViewAttribute *mas_trailing;
 @property (nonatomic, strong, readonly) MASViewAttribute *mas_width;
 @property (nonatomic, strong, readonly) MASViewAttribute *mas_height;
 @property (nonatomic, strong, readonly) MASViewAttribute *mas_centerX;
 @property (nonatomic, strong, readonly) MASViewAttribute *mas_centerY;
 @property (nonatomic, strong, readonly) MASViewAttribute *mas_baseline;
 @property (nonatomic, strong, readonly) MASViewAttribute *(^mas_attribute)(NSLayoutAttribute attr);

 @property (nonatomic, strong, readonly) MASViewAttribute *mas_leftMargin;
 @property (nonatomic, strong, readonly) MASViewAttribute *mas_rightMargin;
 @property (nonatomic, strong, readonly) MASViewAttribute *mas_topMargin;
 @property (nonatomic, strong, readonly) MASViewAttribute *mas_bottomMargin;
 @property (nonatomic, strong, readonly) MASViewAttribute *mas_leadingMargin;
 @property (nonatomic, strong, readonly) MASViewAttribute *mas_trailingMargin;
 @property (nonatomic, strong, readonly) MASViewAttribute *mas_centerXWithinMargins;
 @property (nonatomic, strong, readonly) MASViewAttribute *mas_centerYWithinMargins;

基本和MASConstraintMaker中的屬性一樣,只是每個屬性前面都有mas_前綴,因為這個類是擴展UIView的,為了和系統類中的Attribute區別,所以加了前綴。

 

 

(8)SHORTHAND簡便寫法:Masonry提供了不加mas_前綴的方法,只需要定義幾個宏:

--- MAS_SHORTHAND :定義了MAS_SHORTHAND宏之後,就可以使用UIView,NSArray中不帶mas_前綴的makeConstraint,updateConstraint,remakeConstraint,以及UiView中不帶mas_前綴的Attribute。

--- MAS_SHORTHAND_GLOBALS :直接對equalTo傳入基礎類型,Masonry自動轉化為NSValue對象。

 

(9)with的使用

在Masonry的鏈式語法中,with可以對一個對象的多個屬性進行連接,但也可以不用with.源碼中的解釋是:with是一個可選的語法屬性,沒有任何影響,但是能提高約束的可讀性。

 

(10)小技巧

--- 如果等式兩邊的Attribute是一樣的,可以省略等式右邊的Attribute;

--- 如果是等於關系,並且右邊的view是父view,equalTo也可以省略;

--- multipier默認為1時,可以不寫;

--- offset默認為0時,可以不寫;

--- 所以,如果不嫌麻煩的話,可以對所有的約束添加multipliedBy()和offset(),看起來也會清楚直觀。

 

(11)mas_key屬性的使用:

mas_key相當於View原生的tag屬性一樣,是為了區分不同的View的,mas_key標志的是字符串,更加方便直觀。如果在遇到約束沖突打印Log時,使用Key標識後,會很容易找到沖突位置。我下面會通過一個例子來講解。

 

(12)weakSelf的使用

Masonry的約束也是寫在block中,所以我通過一個宏定義:

 

//定義宏,用於block
#define WeakSelf(weakSelf) __weak __typeof(&*self)weakSelf = self;

 

在block之前定義:

 

WeakSelf(weakSelf);
所以在block中就不使用self,而改用weakSelf即可。

 

(13)關於(8)中提到的兩個宏定義,定義時的位置一定要在#import頭文件之前,如下所示:

 

#define MAS_SHORTHAND
#define MAS_SHORTHAND_GLOBALS
#import "FirstViewController.h"
#import "Masonry.h"

 

我下面通過幾個小例子來作為Masonry的入門:

【1】繪制一個紅色的View,在屏幕中上下左右居中,寬高為200:

 

//繪制一個紅色的View
- (void)setRedView
{
    WeakSelf(weakSelf);

    self.redView = [[UIView alloc] init];
    self.redView.backgroundColor = [UIColor redColor];
    //在設置Autolayout之前,要將view添加到self.view上面
    [self.view addSubview:self.redView];

    [self.redView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.center.mas_equalTo(weakSelf.view);
        make.size.mas_equalTo(CGSizeMake(200, 200));
    }];
}
注意:在對redView設置約束之前,一定要把它添加到self.view中!

 

 

【2】在紅色的View中繪制一個灰色的View,主要學習如何使用復合屬性和單一屬性設置四周邊距:

 

//在紅色的View中繪制一個灰色的View
- (void)setGrayViewEdgeInsetToRedView
{
    WeakSelf(weakSelf);

    self.grayView = [[UIView alloc] init];
    self.grayView.backgroundColor = [UIColor grayColor];
    [self.redView addSubview:self.grayView];

    [self.grayView mas_makeConstraints:^(MASConstraintMaker *make) {
        //可以使用符合屬性設置
        // make.edges.equalTo(weakSelf.redView).with.insets(UIEdgeInsetsMake(20, 20, 20, 20));

        //上述代碼也可以拆分為:
        //可以使用with對同一條約束設置參數
        //        make.top.equalTo(weakSelf.redView).with.offset(20);
        //        make.left.equalTo(weakSelf.redView).with.offset(20);
        //        make.bottom.equalTo(weakSelf.redView).with.offset(-20);
        //        make.right.equalTo(weakSelf.redView).with.offset(-20);

        // 也可以去掉with
        make.top.equalTo(weakSelf.redView).offset(20);
        make.left.equalTo(weakSelf.redView).offset(20);
        make.bottom.equalTo(weakSelf.redView).offset(-20);
        make.right.equalTo(weakSelf.redView).offset(-20);
    }];
}

 

【3】在灰色View裡面繪制兩個等寬等間距的View,設置左右邊距,相互之間的邊距為15,同時自動計算他們的寬度:

 

//在灰色View裡面繪制兩個等寬等間距的View,設置左右邊距、相互之間邊距為15
- (void)setTwoViewInGrayView
{
    WeakSelf(weakSelf);
    UIView *subView1 = [[UIView alloc] init];
    UIView *subView2 = [[UIView alloc] init];

    subView1.backgroundColor = [UIColor orangeColor];
    subView2.backgroundColor = [UIColor blueColor];

    [self.grayView addSubview:subView1];
    [self.grayView addSubview:subView2];

    [subView1 mas_makeConstraints:^(MASConstraintMaker *make) {
        make.centerY.equalTo(weakSelf.grayView.mas_centerY);
        make.left.equalTo(weakSelf.grayView.mas_left).with.offset(15);
        make.right.equalTo(subView2.mas_left).with.offset(-15);
        //設置subView1的高度為grayView高度的0.5.
        make.height.equalTo(weakSelf.grayView).multipliedBy(0.5);
        make.width.equalTo(subView2.mas_width);
    }];

    [subView2 mas_makeConstraints:^(MASConstraintMaker *make) {
        make.centerY.equalTo(weakSelf.grayView.mas_centerY);
        make.left.equalTo(subView1.mas_right).with.offset(15);
        make.right.equalTo(weakSelf.grayView.mas_right).offset(-15);
        make.height.equalTo(weakSelf.grayView).multipliedBy(0.5);
        make.width.equalTo(subView1.mas_width);
    }];

    //以上的兩個約束還有如下簡化的寫法
    [subView1 mas_remakeConstraints:^(MASConstraintMaker *make) {
        //設置subView1的centerY屬性,如果後面的grayView的參數也是centerY的話,就可以省略
        make.centerY.equalTo(weakSelf.grayView);
        //因為默認也是想要和grayView的左邊距對齊,所以可以省略mas_left;
        make.left.equalTo(weakSelf.grayView).with.offset(15);
        //下面的mas_left不能省略,因為前面的參數是right,當前後參數不一致時,不能省略後面的參數
        make.right.equalTo(subView2.mas_left).with.offset(-15);
        make.height.equalTo(weakSelf.grayView).multipliedBy(0.5);
        //可以省略下面subView2的width參數
        make.width.equalTo(subView2);
    }];

    [subView2 mas_remakeConstraints:^(MASConstraintMaker *make) {
        make.centerY.equalTo(weakSelf.grayView);
        make.left.equalTo(subView1.mas_right).with.offset(15);
        make.right.equalTo(weakSelf.grayView).offset(-15);
        make.height.equalTo(weakSelf.grayView).multipliedBy(0.5);
        make.width.equalTo(subView1);
    }];
}

【4】學習設置比例系數:我要繪制一個View,寬度是self.view的0.5倍再減少10,高度是self.view的0.2倍,距離self.view左邊距10,上部緊貼紅色View:
- (void)setMutiplierAndConstant
{
    WeakSelf(weakSelf);
    UIView *yellowView = [[UIView alloc] init];
    yellowView.backgroundColor = [UIColor yellowColor];
    [self.view addSubview:yellowView];

    [yellowView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.width.equalTo(weakSelf.view.mas_width).offset(-10).multipliedBy(0.5);//根據公式,這裡的-10就是constant.
        make.height.equalTo(weakSelf.view.mas_height).multipliedBy(0.2).offset(0);
        make.top.equalTo(weakSelf.redView.mas_bottom).multipliedBy(1).offset(0);
        make.left.equalTo(weakSelf.view.mas_left).multipliedBy(1).offset(10);
    }];
}

【5】使用mas_key屬性,使沖突發生時Log日志變得清晰,如下代碼是帶有沖突的代碼:
- (void)setViewWithKey
{
    UIView *firstView = [[UIView alloc] init];
    firstView.backgroundColor = [UIColor blackColor];
    [self.view addSubview:firstView];

    //這裡使用mas_key參數
    self.view.mas_key = @"self.view";
    firstView.mas_key = @"firstView";

    //寫一個沖突的約束
    [firstView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.size.mas_equalTo(CGSizeMake(100, 100));
        make.left.offset(10);
        make.right.offset(-10);
    }];
}

如果不使用mas_key來標識兩個View,那麼Log打印如下:

 

 Probably at least one of the constraints in the following list is one you don't want.
	Try this:
 (1) look at each constraint and try to figure out which you don't expect;
 (2) find the code that added the unwanted constraint or constraints and fix it.
 (
 "",
 "",
 "",
 ""
 )

 Will attempt to recover by breaking constraint
 

其中打印出的是View的地址,對於有多個View的時候,Log就很難讀了。

 

當設置mas_key後,輸入如下:

 

 Probably at least one of the constraints in the following list is one you don't want.
	Try this:
 (1) look at each constraint and try to figure out which you don't expect;
 (2) find the code that added the unwanted constraint or constraints and fix it.
 (
 "",
 "",
 "",
 ""
 )

 Will attempt to recover by breaking constraint 

對於有可能哪一個View出現的沖突,Log日志就很容易區別。

【6】使用上述(8)談到的兩個宏,使用Masonry時可以省略mas_前綴,下面的代碼是去掉了mas_前綴的,也可以成功編譯運行:

 

- (void)useShorthand
{
    UIView *firstView = [[UIView alloc] init];
    firstView.backgroundColor = [UIColor blackColor];
    [self.view addSubview:firstView];

    self.view.mas_key = @"self.view";
    firstView.mas_key = @"firstView";

    //寫一個沖突的約束
    [firstView makeConstraints:^(MASConstraintMaker *make) {
        make.size.equalTo(CGSizeMake(100, 100));
        make.left.offset(10);
        make.right.offset(-10);
    }];

}

我這裡介紹的Masonry使用還只是一個入門使用,想要更熟練的使用,那麼必須在實際項目中去運用它。當然最好的學習方式就是去閱讀Masonry的源代碼啦。
  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved