iOS-masonry 使用

需要记录的一点:

1.简介

基于NSLayoutConstraint封装的第三方布局框架,实现自动布局,采用链式编程的方式提供给开发者API。系统AutoLayout支持的操作,Masonry都支持。

2.Github地址:

https://github.com/SnapKit/Masonry

3. 集成方式

Masonry支持CocoaPods,可以直接通过podfile文件进行集成,需要在CocoaPods中添加下面代码:

pod 'Masonry'

4.基本用法

--- mas_makeConstraints() 添加约束

--- mas_remakeConstraints()  移除之前的约束,重新添加新的约束

--- mas_updateConstraints()  更新约束,写哪条更新哪条,其他约束不变

--- equalTo()      参数是对象类型,一般是视图对象或者mas_width这样的坐标系对象

-- mas_equalTo()  和上面功能相同,参数可以传递基础数据类型对象,可以理解为比上面的API更强大

--- width()        用来表示宽度,例如代表view的宽度

--- mas_width()    用来获取宽度的值。和上面的区别在于,一个代表某个坐标系对象,一个用来获取坐标系对象的值

asonry为了让代码使用和阅读更容易理解,所以直接通过点语法就可以调用,还添加了and和with两个方法。这两个方法内部实际上什么都没干,只是在内部将self直接返回,功能就是为了更加方便阅读,对代码执行没有实际作用。

例如下面的例子:

make.top.and.bottom.equalTo(self.containerView).with.offset(padding);

其内部代码实现,实际上就是直接将self返回。

-(MASConstraint*)with{

return self;

}

5.更新约束和布局

关于更新约束布局相关的API,主要用以下四个API:

-(void)updateConstraintsIfNeeded  调用此方法,如果有标记为需要重新布局的约束,则立即进行重新布局,内部会调用updateConstraints方法-(void)updateConstraints          重写此方法,内部实现自定义布局过程-(BOOL)needsUpdateConstraints    当前是否需要重新布局,内部会判断当前有没有被标记的约束-(void)setNeedsUpdateConstraints  标记需要进行重新布局

6.UIview 重新布局

-(void)setNeedsLayout 标记为需要重新布局

-(void)layoutIfNeeded   查看当前视图是否被标记需要重新布局,有则在内部调用layoutSubviews方法进行重新布局-(void)layoutSubviews    重写当前方法,在内部完成重新布局操作

7.用法举例

7.1  /**

设置yellow视图和self.view等大,并且有10的内边距。

注意根据UIView的坐标系,下面right和bottom进行了取反。所以不能写成下面这样,否则right、bottom这两个方向会出现问题。

make.edges.equalTo(self.view).with.offset(10);

除了下面例子中的offset()方法,还有针对不同坐标系的centerOffset()、sizeOffset()、valueOffset()之类的方法。

*/

[self.yellowView mas_makeConstraints:^(MASConstraintMaker*make){

make.left.equalTo(self.view).with.offset(10);

make.top.equalTo(self.view).with.offset(10);

make.right.equalTo(self.view).with.offset(-10);

make.bottom.equalTo(self.view).with.offset(-10);}

];

7.2 通过insets简化设置内边距的方式

// 下面的方法和上面例子等价,区别在于使用insets()方法。

[self.blueView mas_makeConstraints:^(MASConstraintMaker*make){

// 下、右不需要写负号,insets方法中已经为我们做了取反的操作了。make.edges.equalTo(self.view).with.insets(UIEdgeInsetsMake(10,10,10,10));}

];

7.3 更新约束

// 设置greenView的center和size,这样就可以达到简单进行约束的目的

[self.greenView mas_makeConstraints:^(MASConstraintMaker*make){

make.center.equalTo(self.view);// 这里通过mas_equalTo给size设置了基础数据类型的参数,参数为CGSize的结构体make.size.mas_equalTo(CGSizeMake(300,300));

}];

// 为了更清楚的看出约束变化的效果,在显示两秒后更新约束。

dispatch_after(dispatch_time(DISPATCH_TIME_NOW,(int64_t)(2.f*NSEC_PER_SEC)),dispatch_get_main_queue(),^{

// 指定更新size,其他约束不变。

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

make.size.mas_equalTo(CGSizeMake(100,100));}];

});

7.4 大于等于和小于等于某个值的约束

[self.textLabel mas_makeConstraints:^(MASConstraintMaker*make){

make.center.equalTo(self.view);

// 设置宽度小于等于200

make.width.lessThanOrEqualTo(@200);

// 设置高度大于等于10

make.height.greaterThanOrEqualTo(@(10));

}];

self.textLabel.text=@"这是测试的字符串。能看到1、2、3个步骤,第一步当然是上传照片了,要上传正面近照哦。上传后,网站会自动识别你的面部,如果觉得识别的不准,你还可以手动修改一下。左边可以看到16项修改参数,最上面是整体修改,你也可以根据自己的意愿单独修改某项,将鼠标放到选项上面,右边的预览图会显示相应的位置。";

textLabel只需要设置一个属性即可

self.textLabel.numberOfLines=0;

7.5 使用基础数据类型当做参数

/**

如果想使用基础数据类型当做参数,Masonry为我们提供了"mas_xx"格式的宏定义。

这些宏定义会将传入的基础数据类型转换为NSNumber类型,这个过程叫做封箱(Auto Boxing)。

"mas_xx"开头的宏定义,内部都是通过MASBoxValue()函数实现的。

这样的宏定义主要有四个,分别是mas_equalTo()、mas_offset()和大于等于、小于等于四个。

*/

[self.redView mas_makeConstraints:^(MASConstraintMaker*make){

make.center.equalTo(self.view);

make.width.mas_equalTo(100);

make.height.mas_equalTo(100);// make.height.equalTo(@(100));

}];

7.6 设置约束优先级

/**

Masonry为我们提供了三个默认的方法,priorityLow()、priorityMedium()、priorityHigh(),这三个方法内部对应着不同的默认优先级。

除了这三个方法,我们也可以自己设置优先级的值,可以通过priority()方法来设置。

*/

[self.redView mas_makeConstraints:^(MASConstraintMaker*make){

make.center.equalTo(self.view);

make.width.equalTo(self.view).priorityLow();

make.width.mas_equalTo(20).priorityHigh();

make.height.equalTo(self.view).priority(200);

make.height.mas_equalTo(100).priority(1000);

}];

Masonry也帮我们定义好了一些默认的优先级常量,分别对应着不同的数值,优先级最大数值是1000。

static const MASLayoutPriority 

MASLayoutPriorityRequired=UILayoutPriorityRequired;staticconstMASLayoutPriority MASLayoutPriorityDefaultHigh=UILayoutPriorityDefaultHigh;staticconstMASLayoutPriority MASLayoutPriorityDefaultMedium=500;staticconstMASLayoutPriority MASLayoutPriorityDefaultLow=UILayoutPriorityDefaultLow;staticconstMASLayoutPriority MASLayoutPriorityFittingSizeLevel=UILayoutPriorityFittingSizeLevel;

7.7 设置约束比例

// 设置当前约束值乘以多少,例如这个例子是redView的宽度是self.view宽度的0.2倍。[self.redView mas_makeConstraints:^(MASConstraintMaker*make){

make.center.equalTo(self.view);

make.height.mas_equalTo(30);

make.width.equalTo(self.view).multipliedBy(0.2);

}];

8.自适应高度

需求举例:父视图上有N个子视图,从上到下依次排列,最下面是一个label,高度根据文案来定,最多X行。

8.1 label自适应高度:

设置label的其他约束,但是不设置高度,只设置举例底部的距离即可。

[self.label mas_makeConstraints:^(MASConstraintMaker *make) {

        make.top.equalTo(self.imgView.mas_bottom).offset(11);

        make.left.equalTo(self.imgView);

        make.right.equalTo(@(-15));

        make.bottom.equalTo(@(0));

    }];

8.2 父视图自适应子视图的高度:

父视图不设置高度,会自动根据子视图最终的高度来设置好高度。

[self.contentView mas_makeConstraints:^(MASConstraintMaker *make) {

            make.left.right.equalTo(@0);

            make.bottom.equalTo(@(-24);

        }];

3.不能立即拿到frame

masonry是建立在autolayout之上的。你没获取到正确的值,那是因为约束还没布局完成。相当于就是我们给一定的约束,系统内部自己去根据约束条件转成对应的frame,而这需要一个过程。

想要拿到正确的frame最好的就是让autolayout完成之后,什么时候完成呢?那就是在layoutsubviews for view or didlayoutsubviews for controller 里获取,当然在控制器的viewdidappear里也拿得到,但是正确做法和最佳做法还是在控制器里的viewdidlayout里获取最好~因为autolayout会根据约束,不停的去改变frame,这方法里最后拿到的frame就是最终姿势.

Masonry的block的回调是立即的;

想立即拿到,需要调用:

[xx.superView layoutIfNeeded];

可以发现,调用[superview layoutIfNeeded];时回调了viewDidLayoutSubviews方法。这就是调用[xx.superView layoutIfNeeded]后能获取到正确frame的原因。

4. 动画更新

和一般动画不同的是,使用Masonry这样放入到动画的block中不能直接让动画生效,只是直接造成控件位移,经过尝试,应当添加如下操作

-(void)beginAnimate{   

 //告知需要更改约束    

[self.view setNeedsUpdateConstraints];    

[UIView animateWithDuration:3 animations:^{       

 [btn mas_updateConstraints:^(MASConstraintMaker *make) {        

 make.right.mas_equalTo(view.mas_right).offset(-100);        

}];        

//告知父类控件绘制,不添加注释的这两行的代码无法生效        

[btn.superview layoutIfNeeded];    

}];

}

其中[btn.superview layoutIfNeeded];是关键的一行,该行必须在动画的block中才能实现动画效果。

注意:多个地方更新不同控件的约束,如果有的需要动画,有的不需要动画,动画会影响其他不做动画的控件,

解决办法是:更新不需要使用动画的控件 也调用下  [superview layoutIfNeeded];

5. 可以和frame混着用

可以某些控件使用 frame,某些控件使用 约束,只要方便就可以。

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

推荐阅读更多精彩内容