Masonry解析

  • Masonry 奕锌、 AutoLayout 、 約束 、 三方庫 阿蝶、 iOS


MagicNumber -> autoresizingMask -> autolayout
以上是純手寫代碼所經(jīng)歷的關(guān)于頁面布局的三個(gè)時(shí)期

在iphone1-iphone3gs時(shí)代:window的size固定為(320,480) 。只需要簡(jiǎn)單計(jì)算一下相對(duì)位置就好了黄绩;

在iphone4-iphone4s時(shí)代:蘋果推出了retina屏 但是給了碼農(nóng)們非常大的福利:window的size不變羡洁;

在iphone5-iphone5s時(shí)代:window的size變了(320,568) 這時(shí)autoresizingMask派上了用場(chǎng)(為啥這時(shí)候不用Autolayout? 因?yàn)檫€要支持ios5唄) 簡(jiǎn)單的適配一下即可。

在iphone6+時(shí)代 window的width也發(fā)生了變化(相對(duì)5和5s的屏幕比例沒有變化) 終于是時(shí)候拋棄autoresizingMask改用autolayout了(不用支持ios5了 相對(duì)于屏幕適配的多樣性來說autoresizingMask也已經(jīng)過時(shí)了)



AutoLayout關(guān)于更新的幾個(gè)方法的區(qū)別:

  • setNeedsLayout:告知頁面需要更新爽丹,但是不會(huì)立刻開始更新筑煮。執(zhí)行后會(huì)立刻調(diào)用layoutSubviews。
  • layoutIfNeeded:告知頁面布局立刻更新粤蝎。所以一般都會(huì)和 setNeedsLayout一起使用真仲。如果希望立刻生成新的frame需要調(diào)用此方法,利用這點(diǎn)一般布局動(dòng)畫可以在更新布局后直接使用這個(gè)方法讓動(dòng)畫生效诽里。
  • layoutSubviews:系統(tǒng)重寫布局
  • setNeedsUpdateConstraints:告知需要更新約束袒餐,但是不會(huì)立刻開始
  • updateConstraintsIfNeeded:告知立刻更新約束
  • updateConstraints:系統(tǒng)更新約束






系統(tǒng)約束

如果使用系統(tǒng)的約束,大致造型如下:

//創(chuàng)建一個(gè)圖片視圖
UIImageView* imgV = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"Oggi.png"]];
//圖片為多個(gè)狗狗 合成的不規(guī)則圖片(不規(guī)矩:非圓形谤狡、非矩形????)

imgV.backgroundColor = [UIColor redColor];//可見到背景色
imgV.translatesAutoresizingMaskIntoConstraints = NO;
imgV.contentMode = UIViewContentModeScaleAspectFit;
[self.view addSubview:imgV];

//imgV左側(cè)與父視圖左側(cè) 多出10個(gè)PX
NSLayoutConstraint* leftConstraint = [NSLayoutConstraint constraintWithItem:imgV attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeLeading multiplier:1.0f constant:10.0f];
//imgV右側(cè)與父視圖右側(cè)對(duì)齊
NSLayoutConstraint* rightConstraint = [NSLayoutConstraint constraintWithItem:imgV attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeTrailing multiplier:1.0f constant:0.0f];
//imgV頂部與父視圖頂部 多出20個(gè)PX
NSLayoutConstraint* topConstraint = [NSLayoutConstraint constraintWithItem:imgV attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeTop multiplier:1.0f constant:20.0f];
//imgV高度為父視圖高度一半
NSLayoutConstraint* heightConstraint = [NSLayoutConstraint constraintWithItem:imgV attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeHeight multiplier:0.5f constant:0.0f];

//iOS 6.0或者7.0調(diào)用addConstraints
//[self.view addConstraints:@[leftConstraint, rightConstraint, topConstraint, heightConstraint]];
//iOS 8.0以后設(shè)置active屬性值
leftConstraint.active = YES;
rightConstraint.active = YES;
topConstraint.active = YES;
heightConstraint.active = YES;

屬性過多灸眼,代碼冗余繁雜!D苟焰宣!
反正我是不想用。

iPhone6s 效果圖






Xib 或者 StoryBoard </br> ??lazy but so convenient

那么還有一個(gè)最懶的方法捕仔,xib和storyBoard拖以及設(shè)置約束匕积。但是維護(hù)起來很繁雜。牽一發(fā)而動(dòng)全身榜跌。(一點(diǎn)小失誤幾乎就得重頭再來闪唆。。钓葫。????)

storyBoard構(gòu)建約束.png

作為一名Coder悄蕾,還是多敲敲代碼吧!享受指尖上的??础浮!????






三方庫Masonry

主角 Masonry登場(chǎng)了

Masonry是一個(gè)基于AutoLayout框架的輕量級(jí)布局框架帆调。比系統(tǒng)自帶
Masonry 源碼:https://github.com/Masonry/Masonry

Masonry支持的一些屬性:

make是MASConstraintMaker類型。MASConstraintMaker給我們提供了22種Attribute類型

  //Basic 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;

這些屬性與NSLayoutAttrubute的對(duì)照表如下:


系統(tǒng)約束屬性


??其他屬性:

  //Margin Attribute
  @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;


  //Convenient Attribute
  @property (nonatomic, strong, readonly) MASConstraint *edges;
  @property (nonatomic, strong, readonly) MASConstraint *size;
  @property (nonatomic, strong, readonly) MASConstraint *center;


更多細(xì)節(jié)豆同,參考:第三方 Masonry約束的使用



工程創(chuàng)建好

工程名:MasonryDemo

這里就不使用下載三方庫番刊,拖入工程的方式導(dǎo)入了。使用cocoapods在終端里導(dǎo)入Masonry 影锈。( 記住vim Podlife前,先pod init創(chuàng)建pod文件 本人精彩犯錯(cuò)?? ?? ?? )

創(chuàng)建Podfile(配置文件)


鍵盤輸入 i芹务,進(jìn)入編輯模式蝉绷,輸入

  platform :ios, '9.0' 
  pod 'Masonry' '~> 1.4'    #'~> 1.4'版本號(hào) 根據(jù)需求可要可不要

然后按Esc,并且輸入“ :”號(hào)進(jìn)入vim命令模式锄禽,然后在冒號(hào)后邊輸入wq

pod install 成功 安裝Masonry庫
安裝Masonry庫 之后 的工程 (點(diǎn)擊 白色工程 打開).png
打開工程后即可看到Masonry所有東西(可謂傾家蕩產(chǎn)~~~)都放入工程里了.png


導(dǎo)入成功后即可使用Masonry約束進(jìn)行布局潜必。

先介紹一個(gè)MACRO (因?yàn)槭褂昧薆lock,需要弱引用)

  #define WS(weakSelf)  __weak __typeof(&*self)weakSelf = self;


首先在Masonry中能夠添加autolayout約束有三個(gè)函數(shù)

  - (NSArray *)mas_makeConstraints:(void(^)(MASConstraintMaker *make))block;
  - (NSArray *)mas_updateConstraints:(void(^)(MASConstraintMaker *make))block;
  - (NSArray *)mas_remakeConstraints:(void(^)(MASConstraintMaker *make))block;
  /*
         mas_makeConstraints 只負(fù)責(zé)新增約束 Autolayout不能同時(shí)存在  兩條針對(duì)于  同一對(duì)象 的約束 否則會(huì)報(bào)錯(cuò)
         mas_updateConstraints 針對(duì)上面的情況 會(huì)  更新  在block中出現(xiàn)的約束 不會(huì)導(dǎo)致出現(xiàn)兩個(gè)相同約束的情況
         mas_remakeConstraints 則會(huì)  清除 之前的 所有約束 僅保留最新的約束
         三種函數(shù)善加利用 就可以應(yīng)對(duì)各種情況了
   */

其次 equalTo 和 mas_equalTo的區(qū)別在哪里呢? 其實(shí) mas_equalTo是一個(gè)MACRO

  #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__)))
  可以看到 mas_equalTo只是對(duì)其參數(shù)進(jìn)行了一個(gè)BOX操作(裝箱)    類似于宏
  MASBoxValue的定義具體可看看其源代碼 

所支持的類型 除了NSNumber支持的那些數(shù)值類型之外
  就只支持CGPoint CGSize UIEdgeInsets

equalTo()的括號(hào)里放:視圖沃但、mas_width等屬性磁滚、@100(對(duì)象);
mas_equalTo()的括號(hào)里放:float(基本數(shù)據(jù)類型)宵晚。

首先導(dǎo)入庫頭文件

  #import <Masonry.h>

再寫一些后面需要的常用定義宏

 #define WS(weakSelf)  __weak __typeof(&*self)weakSelf = self;   //block弱引用

 #define screen_W [UIScreen mainScreen].bounds.size.width       //屏寬
 #define screen_H [UIScreen mainScreen].bounds.size.height      //屏高


-(void)viewDidLoad {}里面

NSMutableArray * imgV_Arr = @[].mutableCopy;
for (int i = 0; i < 10; i ++) {  //構(gòu)建10個(gè)圖片試圖
    UIImageView * imgV = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"Oggi.png"]];
    imgV.backgroundColor = [UIColor colorWithRed:arc4random()%256/255.f green:arc4random()%256/255.f  blue:arc4random()%256/255.f  alpha:1];
  //隨機(jī)色生成

    [imgV_Arr addObject:imgV];//數(shù)組 添加圖片
  
    [self.view addSubview:imgV];
    imgV.frame = CGRectMake(i*screen_W/5.f, 0, screen_W/5.f, screen_H/10.f);
}


WS(ws);     //弱引用    __block修飾
[imgV_Arr[5] mas_makeConstraints:^(MASConstraintMaker *make) {  //第6張圖片處理
    make.center.equalTo(ws.view);             //中心 對(duì)齊
    make.size.mas_equalTo(CGSizeMake(260, 160));//尺寸
}];


[imgV_Arr[6] mas_makeConstraints:^(MASConstraintMaker *make) {  //第7張圖片處理
    make.edges.equalTo(imgV_Arr[5]).with.insets(UIEdgeInsetsMake(20, 20, 20, 20));      // 包含在內(nèi)部   內(nèi)嵌
    
    /* 等價(jià)于 */
    //  make.top.equalTo(imgV_Arr[5]).with.offset(20);
    //  make.left.equalTo(imgV_Arr[5]).with.offset(20);
    //  make.bottom.equalTo(imgV_Arr[5]).with.offset(-20);
    //  make.right.equalTo(imgV_Arr[5]).with.offset(-20);
    
    /* 也等價(jià)于 */
   //  make.top.left.bottom.and.right.equalTo(imgV_Arr[5]).with.insets(UIEdgeInsetsMake(20, 20, 20, 20));  
}];



UIView * backView = [UIView new];//純色 背景視圖
backView.backgroundColor = [UIColor whiteColor];
[self.view addSubview:backView];

[backView mas_makeConstraints:^(MASConstraintMaker *make) {
    make.left.equalTo(ws.view).with.offset(30);
    make.bottom.equalTo(ws.view).with.offset(-10);
    make.right.equalTo(ws.view).with.offset(-50);
    
    make.size.mas_equalTo(CGSizeMake(screen_W, screen_H/3.f));
}];

    UIImageView * imgV7 = imgV_Arr[7];//第8張圖片處理
    UIImageView * imgV8 = imgV_Arr[8];  //第9張圖片處理
    UIImageView * imgV9 = imgV_Arr[9];//第10張圖片處理
    //轉(zhuǎn)換為 視圖格式(??  才對(duì)應(yīng).mas_left垂攘、.mas_right屬性  ??)

    [backView addSubview: imgV7];
    [backView addSubview: imgV8];
    [backView addSubview:imgV9];

    int padding = 10;   //左右間距
    [imgV7 mas_makeConstraints:^(MASConstraintMaker *make) {
    make.centerY.mas_equalTo(backView.mas_centerY);
    make.left.equalTo(backView.mas_left).with.offset(padding);
    make.right.equalTo(imgV8.mas_left).with.offset(-padding);
    make.height.mas_equalTo(@100);//NSNumber類型
    make.width.equalTo(imgV8);
}];
[imgV8 mas_makeConstraints:^(MASConstraintMaker *make) {
    make.centerY.mas_equalTo(backView.mas_centerY);
    make.left.equalTo(imgV7.mas_right).with.offset(padding);
    make.right.equalTo(backView.mas_right).with.offset(-padding);
    make.height.mas_equalTo(backView.mas_height);
    make.width.equalTo(imgV7);
}];


//    動(dòng)畫
[imgV9 mas_updateConstraints:^(MASConstraintMaker *make) {
    make.top.equalTo(backView).offset(30);
    make.bottom.equalTo(imgV7.mas_top).offset(-5);
    make.width.equalTo(@50);
}];
[UIView animateWithDuration:3 animations:^{ //三秒內(nèi) 播放
    [backView layoutIfNeeded];
}];
//   因?yàn)椴季旨s束就是要 脫離frame表達(dá)方式,可是動(dòng)畫是需要根據(jù)這個(gè)來執(zhí)行淤刃,就會(huì)有
 矛盾晒他,但根據(jù)前面說到布局約束的原理,在 某個(gè)時(shí)刻 約束也是會(huì)被 還原 成frame使視圖
顯示逸贾,這個(gè)時(shí)刻可通過 layoutIfNeeded這個(gè)方法來進(jìn)行控制陨仅。

效果:

最終效果圖.png


  • 因?yàn)椴季旨s束就是要 脫離frame表達(dá)方式,可是動(dòng)畫是需要根據(jù)這個(gè)來執(zhí)行铝侵,就會(huì)有矛盾灼伤,但根據(jù)前面說到布局約束的原理,在 某個(gè)時(shí)刻 約束也是會(huì)被 還原 成frame使視圖顯示咪鲜,這個(gè)時(shí)刻可通過 layoutIfNeeded這個(gè)方法來進(jìn)行控制狐赡。

    [UIView animateWithDuration:3 animations:^{ //三秒內(nèi) 播放
      [backView layoutIfNeeded];
    }];
    
下方白色視圖 Masonry動(dòng)畫.gif





Masonry的屬性和類別




后續(xù)有時(shí)間繼續(xù)更新!

后續(xù)有時(shí)間繼續(xù)更新疟丙!

后續(xù)有時(shí)間繼續(xù)更新颖侄!

之后有時(shí)間討論UIScrollView的約束建立

一直說詳細(xì)寫一下“UIScrollView的約束建立”,沒時(shí)間O斫肌览祖!注意的一點(diǎn)就是:UIScrollView的contentSize尺寸大小:
1.若大于里面所有約束好的子控件的整體大小,那么直接顯示完所有的子控件
2.若大于里面所有約束好的子控件的整體(的寬度爽室、高度)大小帘靡,則在其寬度、高度上面把UIScrollView的contentSize拉伸開來

??以后有空再舉了~??????
















goyohol's essay

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末皇钞,一起剝皮案震驚了整個(gè)濱河市悼泌,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌夹界,老刑警劉巖馆里,帶你破解...
    沈念sama閱讀 212,454評(píng)論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡鸠踪,警方通過查閱死者的電腦和手機(jī)丙者,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,553評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來营密,“玉大人械媒,你說我怎么就攤上這事∑捞” “怎么了纷捞?”我有些...
    開封第一講書人閱讀 157,921評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)被去。 經(jīng)常有香客問我主儡,道長(zhǎng),這世上最難降的妖魔是什么惨缆? 我笑而不...
    開封第一講書人閱讀 56,648評(píng)論 1 284
  • 正文 為了忘掉前任糜值,我火速辦了婚禮,結(jié)果婚禮上坯墨,老公的妹妹穿的比我還像新娘寂汇。我一直安慰自己,他們只是感情好畅蹂,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,770評(píng)論 6 386
  • 文/花漫 我一把揭開白布健无。 她就那樣靜靜地躺著,像睡著了一般液斜。 火紅的嫁衣襯著肌膚如雪累贤。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,950評(píng)論 1 291
  • 那天少漆,我揣著相機(jī)與錄音臼膏,去河邊找鬼。 笑死示损,一個(gè)胖子當(dāng)著我的面吹牛渗磅,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播检访,決...
    沈念sama閱讀 39,090評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼始鱼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了脆贵?” 一聲冷哼從身側(cè)響起医清,我...
    開封第一講書人閱讀 37,817評(píng)論 0 268
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎卖氨,沒想到半個(gè)月后会烙,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體负懦,經(jīng)...
    沈念sama閱讀 44,275評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,592評(píng)論 2 327
  • 正文 我和宋清朗相戀三年柏腻,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了纸厉。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,724評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡五嫂,死狀恐怖颗品,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情贫导,我是刑警寧澤抛猫,帶...
    沈念sama閱讀 34,409評(píng)論 4 333
  • 正文 年R本政府宣布,位于F島的核電站孩灯,受9級(jí)特大地震影響闺金,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜峰档,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,052評(píng)論 3 316
  • 文/蒙蒙 一败匹、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧讥巡,春花似錦掀亩、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,815評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至抬驴,卻和暖如春炼七,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背布持。 一陣腳步聲響...
    開封第一講書人閱讀 32,043評(píng)論 1 266
  • 我被黑心中介騙來泰國(guó)打工豌拙, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人题暖。 一個(gè)月前我還...
    沈念sama閱讀 46,503評(píng)論 2 361
  • 正文 我出身青樓按傅,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親胧卤。 傳聞我的和親對(duì)象是個(gè)殘疾皇子唯绍,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,627評(píng)論 2 350

推薦閱讀更多精彩內(nèi)容