Masonry初探

Masonry整理

Masonry是以AutoLayout为基础的轻量级布局框架更加简化了整个约束系统

Masonry三方下载
本文参考:
地址1
地址2
地址3
地址4

*Masonry有哪些属性

@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;

  • (NSArray *)mas_makeConstraints:(void(^)(MASConstraintMaker *make))block;
  • (NSArray *)mas_updateConstraints:(void(^)(MASConstraintMaker *make))block;
  • (NSArray *)mas_remakeConstraints:(void(^)(MASConstraintMaker *make))block;
    • mas_makeConstraints 只负责添加约束 AutoLayout不能同时存在两条针对同一对象的约束否则会报错
    • mas_updateConstraints 针对上面的情况 会更新在block中出现的约束 不会导致出现两个相同约束的情况
    • mas_remakeConstraints 清除之前所有的约束只保留新的约束
**重点:**
**使用mas_makeConstrains方法的元素必须事先添加到父视图中**

* mas_equalTo和equalTo区别:前者比后者多了类型转换操作,支持CGSize CGPoint NSNumber UIEdgeinsets。mas_equalTo是equalTo的封装,equalTo适用于基本数据类型,而mas_equaalTo适用于类似UIEdgeInsetsMake 等复杂类型,基本上它可以替换equalTo。

*  **上左为正 下右为负** 是因为坐标而来的 视图坐标左上为原点 X向右为正 Y向下为正


> 举例比较:
`Make.left.equalTo(@64)` 可以这么写才可以 字面量
`make.left.mas_equalTo(64);` 而mas_equalTo可以不用字面量

1. 先试一下:一个View居中

// 防止block循环引用
__weak typeof (self)weakSelf = self;

UIView *yellow = [UIView new];
yellow.backgroundColor = [UIColor yellowColor];

// 切记添加到父视图中
[self.view addSubview:yellow];
[yellow showPlaceHolder];
/**
* 设置约束
* 使用mas_MakeConstraints:添加约束
*/
[yellow mas_makeConstraints:^(MASConstraintMaker *make) {
// 1.make就是添加约束的控件
// make.left.equalTo 的意思是左侧和谁相同 .offset则是偏移量 上左[为正]下右[为负]
make.top.equalTo(self.view.mas_top).offset(30);// 和父视图顶部间距30
make.left.equalTo(self.view.mas_left).offset(30);// 和父视图左边间距30
make.bottom.equalTo(self.view.mas_bottom).offset(-30);// 和父视图底部间距30
make.right.equalTo(self.view.mas_right).offset(-30);// 和父视图右边间距30

    // 2. 2等价于1 edges边缘的意思 
    make.edges.equalTo(self.view).with.insets(UIEdgeInsetsMake(30, 30, 30, 30));
    
    // 3. 还等价于
    make.top.left.bottom.and.right.equalTo(self.view).with.insets(UIEdgeInsetsMake(30, 30, 30, 30));
    
  // 4.此处给yellow一个size 且让其居中

make.size.mas_equalTo(CGSizeMake(300, 300));
make.center.equalTo(self.view);

}];


> size还可以这么写两者也相同

make.size.mas_equalTo(self.view).offset(-20);
make.size.equalTo(self.view).offset(-20);


居中:

make.centerX.equalTo(self.view.mas_centerX);
make.centerY.equalTo(self.view.mas_centerY);

等同于:
`make.center.mas_equalTo(self.view);`

2. 两个view
* 例1



![如图](http://upload-images.jianshu.io/upload_images/982286-a5a9d1f723d51c61.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
![如图](http://upload-images.jianshu.io/upload_images/982286-aaa302bd647dc316.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

[green mas_makeConstraints:^(MASConstraintMaker *make) {
make.size.mas_equalTo(CGSizeMake(200, 120));// green大小
make.top.mas_equalTo(green.superview).offset(100);// green顶部到它父视图的偏移量

    make.bottom.mas_equalTo(yellow.mas_top).offset(-50);// 50如果为正就是green底部到yellow顶部距离为50 为负就是green下边到yellow上边为50
    make.centerX.equalTo(green.superview.mas_centerX);// 中心点的X坐标和父视图中心点的X相同 说人话就是在中间
}];

[yellow mas_makeConstraints:^(MASConstraintMaker *make) {
   
    make.size.mas_equalTo(CGSizeMake(250, 30)); // 给个size
    make.centerX.equalTo(green.mas_centerX);// centerX和green一样


    
}];

`make.size.equalTo(green); `两个view就相同大小 
等同于

make.width.equalTo(green.mas_width);
make.height.equalTo(green.mas_height);

* 例2:

![两个view](http://upload-images.jianshu.io/upload_images/982286-f4a86f6af9a21d16.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
[green mas_makeConstraints:^(MASConstraintMaker *make) {
    // 添加大小约束
    make.size.mas_equalTo(CGSizeMake(100, 100));
    // 添加左上边距约束
    make.left.and.top.mas_equalTo(20);
}];

[yellow mas_makeConstraints:^(MASConstraintMaker *make) {
    // 大小和上边距约束与green相同
    make.size.and.top.equalTo(green);
    // 添加右边距约束 上左为正下右为负
    make.right.mas_equalTo(-20);
}];
**这里的and和with都没有具体操作只是拿来增加程序可读性**
* 例3:
![例3](http://upload-images.jianshu.io/upload_images/982286-3d5fc83d4e4cd910.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

[green mas_makeConstraints:^(MASConstraintMaker *make) {
// 左上约束20 右侧约束-20
make.left.and.top.mas_equalTo(20);
// 右边约束为-20
make.right.mas_equalTo(-20);
}];

[yellow mas_makeConstraints:^(MASConstraintMaker *make) {
    // 下右约束-20
    make.bottom.and.right.mas_equalTo(-20);
    // 高度和green相同
    make.height.equalTo(green);
    // 顶部到green底部距离为20
    make.top.equalTo(green.mas_bottom).offset(20);
    // 左侧到视图中心的距离为20
    make.left.equalTo(weakSelf.view.mas_centerX).offset(20);
}];

` make.right.equalTo(weakSelf.view).offset(-20);`
**等同于**
`make.right.mas_equalTo(-20);`

* 例4:

![屏幕快照 2015-12-07 上午9.42.41.png](http://upload-images.jianshu.io/upload_images/982286-504a0c4c8ec2fbb6.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
UIView *gray = [UIView new];
gray.backgroundColor = [UIColor grayColor];
[self.view addSubview:gray];
[gray showPlaceHolder];

[gray mas_makeConstraints:^(MASConstraintMaker *make) {
    // 左上下距离父视图都为0
    make.left.and.top.and.bottom.mas_equalTo(0);
    // 宽度为200
    make.width.mas_equalTo(200);
}];
UIView *w = [UIView new];
w.backgroundColor = [UIColor colorWithWhite:0.228 alpha:1.000];
[w showPlaceHolder];
[self.view addSubview:w];

UIView *light = [UIView new];
light.backgroundColor = [UIColor lightGrayColor];
[light showPlaceHolder];
[self.view  addSubview:light];

[w mas_makeConstraints:^(MASConstraintMaker *make) {
    // w底部距离父视图centerY的距离为10
    make.bottom.equalTo(weakSelf.view.mas_centerY).mas_equalTo(-10);
    // 左侧距离gray距离为20
    make.left.equalTo(gray).offset(20);
    // 右侧距离gray距离20
    make.right.equalTo(gray).offset(-20);
    make.height.mas_equalTo(100);
}];
[light mas_makeConstraints:^(MASConstraintMaker *make) {
    // 顶部距离父视图centerY为10
    make.top.equalTo(weakSelf.view.mas_centerY).mas_equalTo(10);
    // 左右和高度与w相同
    make.left.and.right.and.height.equalTo(w);

}];
**上下左右边距**

` make.top.left.bottom.right.equalTo(weakSelf.view).with.insets(UIEdgeInsetsMake(20, 20, 100, 20));`
等价
`make.edges.equalTo(weakSelf.view).with.insets(UIEdgeInsetsMake(20, 20, 100, 20));`

* 例5:
![屏幕快照 2015-12-07 下午3.04.56.png](http://upload-images.jianshu.io/upload_images/982286-84d768961ce98cbf.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)


 [green mas_makeConstraints:^(MASConstraintMaker *make) {
    make.centerY.mas_equalTo(weakSelf.view.mas_centerY);
    make.left.equalTo(weakSelf.view.mas_left).offset(10);
    make.right.equalTo(yellow.mas_left).offset(-10);
    make.height.mas_equalTo(150);
    make.width.equalTo(yellow);
}];
[yellow mas_makeConstraints:^(MASConstraintMaker *make) {
    make.centerY.mas_equalTo(weakSelf.view.mas_centerY);
    make.left.equalTo(green.mas_right).offset(10);
    make.right.equalTo(weakSelf.view.mas_right).offset(-10);
    make.height.mas_equalTo(@150);
    make.width.equalTo(green);
}];
* 例6:

![竖屏](http://upload-images.jianshu.io/upload_images/982286-c13ffecf90e7e4ea.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

![横屏](http://upload-images.jianshu.io/upload_images/982286-9708f83548e23c2d.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

[yellow mas_makeConstraints:^(MASConstraintMaker *make) {
    //make.edges.equalTo(self.view).with.insets(UIEdgeInsetsMake(30, 10, 300, 10));
    make.top.left.equalTo(@20);
    make.right.mas_equalTo(-10);
    
}];

[w mas_makeConstraints:^(MASConstraintMaker *make) {
    make.left.mas_equalTo(20);
    make.bottom.mas_equalTo(weakSelf.view).offset(-20);
    make.height.mas_equalTo(yellow);
    make.top.mas_equalTo(yellow.mas_bottom).offset(20);
    make.width.mas_equalTo(green);
    make.right.mas_equalTo(green.mas_left).offset(-20);

}];

[green mas_makeConstraints:^(MASConstraintMaker *make) {
    make.top.mas_equalTo(yellow.mas_bottom).offset(20);
    make.left.equalTo(w.mas_right).offset(20);
    make.right.equalTo(yellow.mas_right);
    make.height.mas_equalTo(or.mas_height);
}];

[or mas_makeConstraints:^(MASConstraintMaker *make) {
    
    make.top.mas_equalTo(yellow.mas_top).offset(20);
    make.left.mas_equalTo(yellow.mas_left).offset(30);
    make.width.mas_equalTo(bl.mas_width);
    
}];

[cy mas_makeConstraints:^(MASConstraintMaker *make) {
    make.top.mas_equalTo(or.mas_bottom).offset(30);
    make.left.mas_equalTo(or.mas_left);
    make.height.mas_equalTo(or.mas_height);
    make.width.mas_equalTo(or.mas_width);
    make.bottom.mas_equalTo(yellow).offset(-20);
    
}];

[bl mas_makeConstraints:^(MASConstraintMaker *make) {
    make.top.mas_equalTo(or.mas_top);
    make.left.mas_equalTo(or.mas_right).offset(20);
    make.bottom.mas_equalTo(cy.mas_bottom);
    make.right.mas_equalTo(weakSelf.view.mas_right).offset(-20);
    
}];

* ScrollView

![屏幕快照 2015-12-07 下午7.33.20.png](http://upload-images.jianshu.io/upload_images/982286-30cdc629a438604e.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

UIScrollView *scr = [UIScrollView new];
scr.backgroundColor = [UIColor whiteColor];
[self.view addSubview:scr];
[scr mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(self.view).with.insets(UIEdgeInsetsMake(10, 10, 10, 10));
}];

UIView *container = [UIView new];
[scr addSubview:container];
[container mas_makeConstraints:^(MASConstraintMaker *make) {
    make.edges.equalTo(scr);
    make.width.equalTo(scr);
}];

int count = 20;
UIView *lastView = nil;

for (int i = 0; i <= count; i++) {
    UIView *subView = [UIView new];
    [container addSubview:subView];
    subView.backgroundColor = [UIColor colorWithHue:( arc4random() % 256 / 256.0 )saturation:( arc4random() % 128 / 256.0 ) + 0.5 brightness:( arc4random() % 128 / 256.0 ) + 0.5 alpha:1];
    [subView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.left.and.right.equalTo(container);
        make.height.mas_equalTo(@(20 * i));
        if (lastView) {
           // lastView存在时 以其底部为下一个view的顶部
            make.top.mas_equalTo(lastView.mas_bottom);
        } else {
            // lastView不存在时 以父视图的顶部为基准
            make.top.mas_equalTo(container.mas_top);
        }
    }];
    lastView = subView;
}

[container mas_makeConstraints:^(MASConstraintMaker *make) {
    make.bottom.equalTo(lastView.mas_bottom);
}];


#####键盘监听
如图:

![屏幕快照 2015-12-07 下午8.55.10.png](http://upload-images.jianshu.io/upload_images/982286-69670567377619c2.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)


![屏幕快照 2015-12-07 下午8.55.22.png](http://upload-images.jianshu.io/upload_images/982286-83f374bb313be9ef.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

`mas_updateConstraints` 利用它来更新约束
初始时约束:


[_textField mas_makeConstraints:^(MASConstraintMaker *make) {
make.size.mas_equalTo(CGSizeMake(200, 30));
make.bottom.mas_equalTo(-40);
make.centerX.equalTo(weakSelf.view.mas_centerX);
}];


键盘弹出在消息方法里更新约束:

-(void)keyBoardWillShow:(NSNotification*)noti {
// 获取键盘基本信息(动画时长与键盘高度)
NSDictionary *userInfo = [noti userInfo];
CGRect rect =
[userInfo[UIKeyboardFrameBeginUserInfoKey] CGRectValue];

CGFloat keyboardHeight = CGRectGetHeight(rect);
CGFloat keyboardDuration =
[userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue];

// 修改下边距约束
[_textField mas_updateConstraints:^(MASConstraintMaker *make) {
    make.bottom.mas_equalTo(-keyboardHeight);
}];

// 更新约束

[UIView animateWithDuration:keyboardDuration animations:^{
    [self.view layoutIfNeeded];
}];

}

键盘收起时在textField代理方法中再次更新约束

-(void)keyboardWillDisappear:(NSNotification *)noti {
// 获取键盘基本信息(动画时长与键盘高度)
NSDictionary *userInfo = [noti userInfo];
CGRect rect =
[userInfo[UIKeyboardFrameBeginUserInfoKey] CGRectValue];

// CGFloat keyboardHeight = CGRectGetHeight(rect);
CGFloat keyboardDuration =[userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue];

[_textField mas_updateConstraints:^(MASConstraintMaker *make) {
    make.bottom.mas_equalTo(-40);
}];
[UIView animateWithDuration:keyboardDuration animations:^{
    [self.view layoutIfNeeded];
}];

}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,684评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,143评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,214评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,788评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,796评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,665评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,027评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,679评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,346评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,664评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,766评论 1 331
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,412评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,015评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,974评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,073评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,501评论 2 343

推荐阅读更多精彩内容