Masnory的详细使用

Masonry简介

Masonry是一个轻量级的布局框架,它拥有自己的描述语法(采用更优雅的链式语法封装)来自动布局,具有很好可读性且同时支持iOS和Max OS X等。

总之,对于侧重写代码的coder,请你慢慢忘记Frame,喜欢Masonry吧

使用前的准备

若是你对于自动布局很熟练的话,再接触这个第三方Masonry很容易上手的,对UI界面显示的控件的约束本质都是相同的,现在呢,我一般都是喜欢在控制器里导入#import "Masonry.h"之前再添加两个宏,来提高App的开发效率。

//1. 对于约束参数可以省去"mas_"#defineMAS_SHORTHAND

//2. 对于默认的约束参数自动装箱#defineMAS_SHORTHAND_GLOBALS

即:需要我们导入的框架与宏如下

//define this constant if you want touseMasonrywithoutthe'mas_'prefix#defineMAS_SHORTHAND//definethisconstantifyou wanttoenableauto-boxingfordefaultsyntax#defineMAS_SHORTHAND_GLOBALS#import"Masonry.h"//宏必须添加在头文件前面

添加约束前提:被约束的必须有父控件,其中约束项都必须是UIView或子类的实例。

约束的属性

在此我就列举几个可能不太熟悉的吧

@property(nonatomic,strong,readonly) MASConstraint *leading;//首部@property(nonatomic,strong,readonly) MASConstraint *trailing;//尾部@property(nonatomic,strong,readonly) MASConstraint *baseline;//文本基线

约束的三种方法

/** //这个方法只会添加新的约束 [blueView mas_makeConstraints:^(MASConstraintMaker *make){

}]; // 这个方法会将以前的所有约束删掉,添加新的约束 [blueView mas_remakeConstraints:^(MASConstraintMaker *make){

}]; // 这个方法将会覆盖以前的某些特定的约束 [blueView mas_updateConstraints:^(MASConstraintMaker *make){

}]; */`

常见约束的各种类型

/**

1.尺寸:width、height、size

2.边界:left、leading、right、trailing、top、bottom

3.中心点:center、centerX、centerY

4.边界:edges

5.偏移量:offset、insets、sizeOffset、centerOffset

6.priority()约束优先级(0~1000),multipler乘因数, dividedBy除因数

*/

Masonry约束易忽略的技术点

使用Masonry不需要设置控件的translatesAutoresizingMaskIntoConstraints属性为NO;

防止block中的循环引用,使用弱引用(这是错误观点),在这里block是局部的引用,block内部引用self不会造成循环引用的

__weak typeof (self) weakSelf = self;(没必要的写法)

Masonry约束控件出现冲突的问题

当约束冲突发生的时候,我们可以设置view的key来定位是哪个view

redView.mas_key = @"redView";

greenView.mas_key = @"greenView";

blueView.mas_key = @"blueView";

若是觉得这样一个个设置比较繁琐,怎么办呢,Masonry则提供了批量设置的宏MASAttachKeys

MASAttachKeys(redView,greenView,blueView); //一句代码即可全部设置

约束iconView距离各个边距为30

[iconViewmakeConstraints:^(MASConstraintMaker*make){      make.edges.equalTo(self.view).insets(UIEdgeInsetsMake(30,30,30,30));}];

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__)))

得出结论:mas_equalTo只是对其参数进行了一个BOX(装箱) 操作,目前支持的类型:数值类型(NSNumber)、 点(CGPoint)、大小(CGSize)、边距(UIEdgeInsets),而equalTo:这个方法不会对参数进行包装。

//常见约束的写法 这里太简单了 ,就不备注了[iconView makeConstraints:^(MASConstraintMaker *make) {        make.right.equalTo(self.view).offset(-30);        make.top.equalTo(self.view).offset(30);        make.height.width.equalTo(100);//== make.size.equalTo(100);//make.size.mas_equalTo(self.view).multipliedBy(0.5);//make.top.greaterThanOrEqualTo(self.view).offset(padding);}];

[redViewmas_makeConstraints:^(MASConstraintMaker*make){        make.top.equalTo(superview.mas_top).with.offset(10);  //with 增强可读性make.left.equalTo(greenView.mas_right).and.offset(10); //and 增强可读性make.bottom.equalTo(blueView.mas_top).offset(-10);make.right.equalTo(superview.mas_right).offset(-10);make.width.equalTo(greenView.mas_width);make.height.equalTo(@[greenView, blueView]); //约束参数相同可以通过数组}];

更新约束的问题

例如:控制器有个按钮,若是点击按钮,则按钮本身的大小、位置会随机改变

监听按钮点击

[self.btnaddTarget:selfaction:@selector(didClickBtn:) forControlEvents:UIControlEventTouchUpInside];

处理事件

(void) didClickBtn:(UIButton*)button {self.btnSize=CGSizeMake(self.btnSize.width*1.3,self.btnSize.height*1.3);//设置一个属性(btnSize)保存其大小的变化//1.告知需要更新约束,但不会立刻开始,系统然后调用updateConstraints[selfsetNeedsUpdateConstraints];//2.告知立刻更新约束,系统立即调用updateConstraints[selfupdateConstraintsIfNeeded];//3.这里动画当然可以取消,具体看项目的需求//系统block内引用不会导致循环引用,block结束就会释放引用对象[UIViewanimateWithDuration:0.4animations:^{      [selflayoutIfNeeded];//告知页面立刻刷新,系统立即调用updateConstraints}];}

苹果官方建议:添加/更新约束在这个方法(updateConstraints)内

// this is Apple's recommended place for adding/updating constraints- (void)updateConstraints {//更新约束[self.btnupdateConstraints:^(MASConstraintMaker *make) {        make.center.equalTo(self);        make.width.equalTo(@(self.buttonSize.width)).priorityLow();        make.height.equalTo(@(self.buttonSize.height)).priorityLow();        make.width.lessThanOrEqualTo(self);        make.height.lessThanOrEqualTo(self);    }];//according to apple super should be called at end of method//最后必须调用父类的更新约束[superupdateConstraints];}

设置requiresConstraintBasedLayout为YES

+ (BOOL)requiresConstraintBasedLayout{returnYES;//重写这个方法 若视图基于自动布局的}

重置约束的问题

对于控件的重新约束,则之前的约束都是无效的,步骤都更新约束一样的,只是在updateConstraints方法内的约束方法改为了remakeConstraints,直接贴代码吧(仍以按钮为例,其他原理都是相同的)

//首先监听按钮[self.btnaddTarget:selfaction:@selector(didClickBtn:) forControlEvents:UIControlEventTouchUpInside];//处理事件- (void) didClickBtn :(UIButton*)button{  (...)//触发条件[selfsetNeedsUpdateConstraints];    [selfupdateConstraintsIfNeeded];/**

*  动画展示变化 - 这句代码可有可无,参考项目具体的需求

*  [UIView animateWithDuration:0.4 animations:^{

*        [self layoutIfNeeded];

*  }];

*/}//重置约束- (void)updateConstraints {    [self.btnremakeConstraints:^(MASConstraintMaker *make) {      .....    }];    [superupdateConstraints]; }+ (BOOL)requiresConstraintBasedLayout{returnYES;//重写这个方法 若视图基于自动布局的}

多个(2个以上)控件的等间隔排序显示

首先介绍2个函数

/**

*  axisType        轴线方向

*  fixedSpacing    间隔大小

*  fixedItemLength  每个控件的固定长度/宽度

*  leadSpacing      头部间隔

*  tailSpacing      尾部间隔

*

*///1. 等间隔排列 - 多个控件间隔固定,控件长度/宽度变化- (void)mas_distributeViewsAlongAxis:(MASAxisType)axisTypewithFixedSpacing:(CGFloat)fixedSpacing leadSpacing:(CGFloat)leadSpacingtailSpacing:(CGFloat)tailSpacing;//2. 等间隔排列 - 多个固定大小固定,间隔空隙变化- (void)mas_distributeViewsAlongAxis:(MASAxisType)axisTypewithFixedItemLength:(CGFloat)fixedItemLengthleadSpacing:(CGFloat)leadSpacingtailSpacing:(CGFloat)tailSpacing;

//首先添加5个视图NSMutableArray *array= [NSMutableArraynew];for(inti =0; i <5; i ++) {        UIView *view = [UIViewnew];        view.backgroundColor = [UIColor greenColor];        [self addSubview:view];        [arrayaddObject:view];//保存添加的控件}//水平方向控件间隔固定等间隔[arraymas_distributeViewsAlongAxis:MASAxisTypeHorizontal withFixedSpacing:15leadSpacing:10tailSpacing:10];            [arraymakeConstraints:^(MASConstraintMaker *make) {                make.top.equalTo(50);                make.height.equalTo(70);            }];//水平方向宽度固定等间隔[arraymas_distributeViewsAlongAxis:MASAxisTypeHorizontal withFixedItemLength:70leadSpacing:10tailSpacing:10];            [arraymakeConstraints:^(MASConstraintMaker *make) {//数组额你不必须都是viewmake.top.equalTo(50);                make.height.equalTo(70);            }];

水平方向等间隔.png

水平方向控件宽度固定等间隔.png

多行label的约束问题

对于UILabel文字内容多的问题,个人觉得Masonry约束设置的非常简单优雅,在此非常感谢Masonry的作者@Robert Payne

//创建labelself.label= [UILabelnew];self.label.numberOfLines=0;self.label.lineBreakMode=NSLineBreakByTruncatingTail;self.label.text=@"有的人,没事时喜欢在朋友圈里到处点赞,东评论一句西评论一句,比谁都有存在感。等你有事找他了,他就立刻变得很忙,让你再也找不着。真正的朋友,平常很少联系。可一旦你遇上了难处,他会立刻回复你的消息,第一时间站出来帮你。所谓的存在感,不是你有没有出现,而是你的出现有没有价值。存在感,不是刷出来的,也不是说出来的。有存在感,未必是要个性锋芒毕露、甚至锋利扎人。翩翩君子,温润如玉,真正有存在感的人,反而不会刻意去强调他的存在感。他的出现,永远都恰到好处。我所欣赏的存在感,不是长袖善舞巧言令色,而是对他人的真心关照;不是锋芒毕露计较胜负,而是让人相处得舒服;不是时时刻刻聒噪不休,而是关键时刻能挺身而出。别总急着出风头,希望你能有恰到好处的存在感。";    [selfaddSubview:self.label];    [self.labelmakeConstraints:^(MASConstraintMaker *make) {        make.left.top.equalTo(10);        make.right.equalTo(-10);    }];//添加约束- (void)layoutSubviews {//1. 执行 [super layoutSubviews];[superlayoutSubviews];//2. 设置preferredMaxLayoutWidth: 多行label约束的完美解决self.label.preferredMaxLayoutWidth= [UIScreenmainScreen].bounds.size.width-20;//3. 设置preferredLayoutWidth后,需要再次执行 [super layoutSubviews];//其实在实际中这步不写,也不会出错,官方解释是说设置preferredLayoutWidth后需要重新计算并布局界面,所以这步最好执行[superlayoutSubviews];}

多行label约束.png

UIScrollView的问题

原理同自动布局一样 UIScrollView上添加UIView

UIView上添加需要显示的控件 UIScrollView滚动高度取决于显示控件的总高度

对子控件做好约束,可达到控制UIView的大小

//创建滚动视图UIScrollView*scrollView = [UIScrollViewnew];self.scrollView= scrollView;    scrollView.backgroundColor= [UIColorgrayColor];    [selfaddSubview:scrollView];    [self.scrollViewmakeConstraints:^(MASConstraintMaker *make) {        make.edges.equalTo(self);    }];    [selfsetUpContentView];//添加内容视图- (void)setUpContentView {//约束UIScrollView上contentViewUIView*contentView = [UIViewnew];    [self.scrollViewaddSubview:contentView];    [contentView makeConstraints:^(MASConstraintMaker *make) {        make.edges.equalTo(self.scrollView);        make.width.equalTo(self.scrollView);//此处必填 - 关键点}];//添加控件到contentView,约束原理与自动布局相同UIView*lastView;CGFloatheight =30;for(inti =0; i <15; i ++) {UIView*view =UIView.new;        view.backgroundColor= [UIColorcolorWithRed:arc4random() %255/256.0green:arc4random() %255/256.0blue:arc4random() %255/256.0alpha:1.0];        [contentView addSubview:view];        [view makeConstraints:^(MASConstraintMaker *make) {            make.top.equalTo(lastView ? lastView.bottom: @0);            make.left.equalTo(0);            make.width.equalTo(contentView.width);            make.height.equalTo(height);        }];        height +=30;        lastView = view;    }    [contentView makeConstraints:^(MASConstraintMaker *make) {        make.bottom.equalTo(lastView.bottom);    }];}

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

推荐阅读更多精彩内容