详解布局Masonry

1.概念

Masonry是一个轻量级的布局框架,拥有自己的描述语法 采用更优雅的链式语法封装自动布局 简洁明了 并具有高可读性 而且同时支持 iOS 和 Mac OS X;是AutoLayout的一个第三方类库,用链式语法封装了冗长的AutoLayout代码,因此学习成本相对于官方提供的AutoLayout,以及VFL语言而言,低上很多很多...(用于纯代码布局);使用的时候导入头文件#import "Masonry.h"
2.支持的属性(如字面意思) 详解布局Masonry
文章图片
屏幕快照 2016-12-30 下午4.22.01.png
备注:
1.简单的语法总结
with和and
基本没用过,方法的结果是返回对象本身,就是对其没有任何的操作.有人说就是为了代码的可读性,我道行太浅感觉有与没有差别不大.
  1. 用masonry时候,比如写距离上面控件10;若不标明是距离上面控件的下边界10,则默认是距离其上边界10,导致可能显示不出来,盖住。注意!!
3.三种设置约束的方法
mas_makeConstraints //第一次生成约束使用 给view添加约束,约束方式有几种,分别是边距,宽,高,左上右下距离,基准线。添加过 约束后可以有修正,修正有offset(位移)修正和multipliedBy(倍率)修正。 (语法有make.equalTo or make.greaterThan Or EqualTo or make.lessThanOrEqualTo + 倍数和位移修正。 使用 mas_makeConstraints方法的元素必须事先添加到父元素的中)mas_updateConstraints //针对上面的情况 会更新在block中出现的约束 不会导致出现两个相同约束的情况 mas_remakeConstraints //重新生成约束,会将之前的所有约束先去掉(一般约束好一个控件,然后在特定情况下想重新布局,就用这个方法)

使用注意:在循环cell,如果有代码重复调用的地方,一定要使用mas_remakeConstraints,以此防止循环的时候生成相同的约束,影响性能,甚至,能使用make的地方基本都可以用remake进行代替,防止生成无谓的约束
mas_updateConstraints 针对上面的情况 会更新block中出现 的约束 不会导致出现两个相同的约束的情况注意: 同一个对象 使用mas_updateConstraints 一定要保证block中要更新的元素是 其使用mas_makeConstraints 设置的约束,如下就是正确的 则不会出现约束冲突问题[testView mas_updateConstraints:^(MASConstraintMaker *make) { make.bottom.equalTo(view1.mas_top).offset(-60); 必须是 同一参照对象(都是以view1)同一参照属性(都是以view1的mas_top) }]; 但是下面的就不对了 就会出现约束冲突 在iOS 7 及其以下会出现由于约束冲突出现的崩溃[testView mas_updateConstraints:^(MASConstraintMaker *make) { make.bottom.equalTo(view2.mas_top).offset(-10); make.centerX.equalTo(view4.mas_centerX); 原因1:不同一参照对象 (原来是view1 现在是view2) 原因2 testView 在 mas_makeConstraints中没有设置 center 所以无法更新 }]; 解决办法:使用mas_remakeConstraints 清除原来的约束 重新设置约束; }];

4.简单例子
例1: UIView *view = [[UIView alloc] init]; view.backgroundColor = [UIColor redColor]; [self.view addSubview:view]; //一定要先加入父控件,否则报错 [view mas_makeConstraints:^(MASConstraintMaker *make) {make.edges.equalTo(view.superview).insets(UIEdgeInsetsMake(20, 20, 20, 20)); }]; **等价于**[view mas_makeConstraints:^(MASConstraintMaker *make) {make.left.right.top.bottom.equalTo(view.superview).insets(UIEdgeInsetsMake(20, 20, 20, 20)); }]; **等价于**[view mas_makeConstraints:^(MASConstraintMaker *make) {make.left.equalTo(view.superview).offset(20); make.top.equalTo(view.superview).offset(20); make.right.equalTo(view.superview).offset(-20); make.bottom.equalTo(view.superview).offset(-20); }];

写法: [imgV mas_makeConstraints:^(MASConstraintMaker *make) {make.size.mas_equalTo(CGSizeMake(17., 38.)); make.left.equalTo(_startTimeLb); make.top.equalTo(_startTimeLb.mas_bottom).with.offset(10.); }]; make.height.greaterThanOrEqualTo(self.mas_bottom).offset(5); // 大于等于约束 mas_lessThanOrEqualTo:小于等于

写法: [self.tableView mas_makeConstraints:^(MASConstraintMaker *make) {make.top.bottom.left.right.mas_equalTo(@(0)); }];

5.细节之处
1.关于mas_equalTo
Masonry表示相等有两种方法:equalTo和mas_equalTo
mas_equalTo其实就是多了一层处理的宏而已,因为equalTo并不支持基本数据类型;例如高度为300的约束中,可以这样写mak.height.equalTo(@300); 或者这样写mak.height.mas_equalTo(300);
masequalTo 比equalTo多了类型转换操作,一般来说,大多数时候两个方法都是 通用的,但是对于数值元素使用mas_equalTo。对于对象或是多个属性的处理,使用equalTo。
mas_equalTo:这个方法会对参数进行封装( 可以跟数据和对象 )
equalTo:这个方法不会对参数进行封装( 后面括号里面必须是对象 )
现在的 mas_equalTo: > equalTo:
注意比例multipliedBy的使用:
make.width.equalTo(self.view.mas_width).multipliedBy(0.5); //设置宽度为self.view的一半,multipliedBy是倍数的意思,也就是,使宽度等于self.view宽度的0.5倍
6.Masonry布局时涉及动画
动画问题,和普通的方法实现差不多,重点只是修改约束后调用:
[view.superview layoutIfNeeded]; 而已
比如:
[view mas_makeConstraints:^(MASConstraintMaker *make) { make.top.mas_equalTo(400); make.left.mas_equalTo(100); make.size.mas_equalTo(CGSizeMake(100, 100)); }]; [view.superview layoutIfNeeded]; //如果其约束还没有生成的时候需要动画的话,就请先 强制刷新后才写动画,否则所有没生成的约束会直接跑动画 [UIView animateWithDuration:3 animations:^{ [view mas_updateConstraints:^(MASConstraintMaker *make) {make.left.mas_equalTo(200); }]; [view.superview layoutIfNeeded]; //强制绘制 }];

相关链接:http://www.cocoachina.com/ios/20141010/9869.html
7. Masonry与Frame混用
需要调用方法layoutIfNeeded才会有效
看例子:
UIView *parent = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)]; UIImageView *child = [UIView alloc] init]; [parent addSubview:child]; [child mas_makeConstraints:^(MASConstraintMaker *make) { make.size.mas_equalTo(CGSizeMake(20,20)); make.top.left.mas_equalTo(50); }]; NSLog(@"%@",redView); 打印结果: ** >**

1.可以发现,虽然使用Masonry进行布局和约束,但是子视图child的frame仍然为(0, 0, 0 ,0)
2.原因:使用masonry的实质是调用了ios7以后的autolayout,如果要更新frame,需要调用layoutIfNeeded函数进行布局,然后所约束的控件才会按照约束条件,生成当前布局相应的frame和bounds。而调用layoutIfNeeded的目的是让系统调用layoutSubviews方法,我们也可以直接在这个方法里获取frame,因为这时候开始layout subviews,Masonry已经计算出了真实的frame

详解布局Masonry
文章图片
屏幕快照 2017-10-26 下午2.20.01.png
源码解析 - Masonry:https://www.jianshu.com/p/2fe9568fd3f5
8.相关链接
详解布局Masonry
文章图片
屏幕快照 2016-12-30 下午4.43.16.png
详解布局Masonry
文章图片
详解布局Masonry
文章图片
屏幕快照 2016-12-30 下午4.39.22.png
详解布局Masonry
文章图片

SDAutoLayout
https://github.com/gsdios/SDAutoLayout
MyLinearLayout
https://github.com/youngsoft/MyLinearLayout
Masonry介绍与使用实践(快速上手Autolayout)
UIScrollview与Autolayout的那点事
masonry:http://geek.csdn.net/news/detail/133417?ref=myread
备注
使用苹果原生方法时:
注意要将一属性关掉试图的属性self.view.autoresizingMask=NO; 或者按钮的button.translatesAutoresizingMaskIntoConstraints=NO;
其他相关有关于自动布局的:

QQ图片20160330100029.png 【详解布局Masonry】

    推荐阅读