masonry

为什么要做这个笔记

masonry 可以说是当前iOS开发中最流行的Autolayout框架,其极大的简化了苹果原生提供的AutoLayout语法。目前很多大厂也是用的这个自动布局框架,我司也在用。在此之前我一只在用另一个叫SDAutolayout的自动布局库,所以masonry是个初学者,如果写得不好的地方还希望大佬指点江山。经过前段时间的开发项目,对masonry框架有了大致的认识,用法上面基本能解决所有布局问题。

masonry 基础约束用法

首先先提及一下,view 在执行 masonry 布局之前必须添加到父视图上

约束的写法有好几种,我先拿三种来举例

第一种。mas_equalTo()方法传入一个依赖的约束边,如下面示例中“self.view.mas_left”,后面跟着 mas_offset()方法可以传入一个值,这个值是相对于所依赖约束的偏移量。mas_offset()也可以不写,默认偏移0。

UIView*demoView=[[UIViewalloc]init];demoView.backgroundColor=UIColor.greenColor;[self.view addSubview:demoView];[demoView mas_makeConstraints:^(MASConstraintMaker*make){make.left.mas_equalTo(self.view.mas_left).mas_offset(50);//左边相对于self.view 的 left 偏移50个单位        make.right.mas_equalTo(self.view.mas_right).mas_offset(-50);//右边相对于self.view 的 right 偏移-50个单位        make.top.mas_equalTo(self.view.mas_top).mas_offset(100);//顶边相对于self.view 的 top 偏移100个单位        make.bottom.mas_equalTo(self.view.mas_bottom).mas_offset(-100);//底边相对于self.view 的 bottom 偏移-100个单位}];

第二种。mas_equalTo()只需要传入相对的约束的视图,不需要指定约束边,默认取前面第一个需要添加约束的边

UIView*demoView=[[UIViewalloc]init];demoView.backgroundColor=UIColor.greenColor;[self.view addSubview:demoView];[demoView mas_makeConstraints:^(MASConstraintMaker*make){make.left.mas_equalTo(self.view).mas_offset(50);//等价于 make.left.mas_equalTo(self.view.mas_left).mas_offset(50);make.right.mas_equalTo(self.view).mas_offset(-50);//等价于 make.right.mas_equalTo(self.view.mas_right).mas_offset(-50);make.top.mas_equalTo(self.view).mas_offset(100);//等价于 make.top.mas_equalTo(self.view.mas_top).mas_offset(100);make.bottom.mas_equalTo(self.view).mas_offset(-100);//等价于 make.bottom.mas_equalTo(self.view.mas_bottom).mas_offset(-100);}];

第三种。mas_equalTo() 传入一个值,这个值就是相对于依赖父视图对应相同约束的偏移量

UIView*demoView=[[UIView alloc]init];demoView.backgroundColor=UIColor.greenColor;[self.view addSubview:demoView];[demoView mas_makeConstraints:^(MASConstraintMaker*make){make.left.mas_equalTo(50);//等价于 make.left.mas_equalTo(demoView.superview.mas_left).mas_offset(50);make.right.mas_equalTo(-50);//等价于 make.right.mas_equalTo(demoView.superview.mas_right).mas_offset(-50);make.top.mas_equalTo(100);//等价于 make.top.mas_equalTo(demoView.superview.mas_top).mas_offset(100);make.bottom.mas_equalTo(-100);//等价于 make.bottom.mas_equalTo(demoView.superview.mas_bottom).mas_offset(-100);}];

三种写法结果是一致的,效果图如下

WechatIMG38.png

看你个人喜欢用哪一种,我个人比较懒,喜欢用第三种,所以都是以第三种写法作为描述

居左上

YYLabel*leftTopLabel=[[YYLabel alloc]init];leftTopLabel.backgroundColor=UIColor.redColor;leftTopLabel.text=@"居左上";leftTopLabel.textColor=UIColor.whiteColor;leftTopLabel.textAlignment=NSTextAlignmentCenter;leftTopLabel.textVerticalAlignment=YYTextVerticalAlignmentCenter;[demoView addSubview:leftTopLabel];[leftTopLabel mas_makeConstraints:^(MASConstraintMaker*make){make.left.mas_offset(0);make.top.mas_equalTo(0);make.height.mas_equalTo(100);make.width.mas_equalTo(100);}];

效果如下

WeChatc5eb1b8916c66b1c53873306fe0597b1.png

居左下

YYLabel*leftBottomLabel=[[YYLabel alloc]init];leftBottomLabel.backgroundColor=UIColor.redColor;leftBottomLabel.text=@"居左下";leftBottomLabel.textColor=UIColor.whiteColor;leftBottomLabel.textAlignment=NSTextAlignmentCenter;leftBottomLabel.textVerticalAlignment=YYTextVerticalAlignmentCenter;[demoView addSubview:leftBottomLabel];[leftBottomLabel mas_makeConstraints:^(MASConstraintMaker*make){make.left.mas_offset(0);make.bottom.mas_equalTo(0);make.height.mas_equalTo(100);make.width.mas_equalTo(100);}];

效果如下

WeChatb3f1265f09aadcd9e120047158e567cf.png

居右上

YYLabel*rightTopLabel=[[YYLabel alloc]init];rightTopLabel.backgroundColor=UIColor.redColor;rightTopLabel.text=@"居右上";rightTopLabel.textColor=UIColor.whiteColor;rightTopLabel.textAlignment=NSTextAlignmentCenter;rightTopLabel.textVerticalAlignment=YYTextVerticalAlignmentCenter;[demoView addSubview:rightTopLabel];[rightTopLabel mas_makeConstraints:^(MASConstraintMaker*make){make.right.mas_offset(0);make.top.mas_equalTo(0);make.height.mas_equalTo(100);make.width.mas_equalTo(100);}];

WechatIMG41.jpeg

居右下

YYLabel*rightBottomLabel=[[YYLabel alloc]init];rightBottomLabel.backgroundColor=UIColor.redColor;rightBottomLabel.text=@"居右下";rightBottomLabel.textColor=UIColor.whiteColor;rightBottomLabel.textAlignment=NSTextAlignmentCenter;rightBottomLabel.textVerticalAlignment=YYTextVerticalAlignmentCenter;[demoView addSubview:rightBottomLabel];[rightBottomLabel mas_makeConstraints:^(MASConstraintMaker*make){make.right.mas_offset(0);make.bottom.mas_equalTo(0);make.height.mas_equalTo(100);make.width.mas_equalTo(100);}];

WechatIMG42.jpeg

垂直水平居中

YYLabel*centerLabel=[[YYLabel alloc]init];centerLabel.backgroundColor=UIColor.redColor;centerLabel.text=@"居中";centerLabel.textColor=UIColor.whiteColor;centerLabel.textAlignment=NSTextAlignmentCenter;centerLabel.textVerticalAlignment=YYTextVerticalAlignmentCenter;[demoView addSubview:centerLabel];[centerLabel mas_makeConstraints:^(MASConstraintMaker*make){make.center.mas_equalTo(0);make.height.mas_equalTo(100);make.width.mas_equalTo(100);}];

WechatIMG43 1.jpeg

子控件来撑起父控件的高度

平常在开发过程中,经常有这种情况就是父控件高度是根据子控件内容动态变化,用masonry来实现这个功能相当简单,这里有几个知识点;

约束类对象MASConstraint,通过点进mas_makeConstraints:方法的实现,源码如下

-(NSArray*)mas_makeConstraints:(void(^)(MASConstraintMaker*))block{self.translatesAutoresizingMaskIntoConstraints=NO;MASConstraintMaker*constraintMaker=[[MASConstraintMaker alloc]initWithView:self];block(constraintMaker);return[constraintMaker install];}

咋们暂且先不管MASConstraintMaker类,找到最后一句constraintMaker对象调用了install方法并返回;进入到这个install的实现,源码实现如下

-(NSArray*)install{if(self.removeExisting){NSArray*installedConstraints=[MASViewConstraint installedConstraintsForView:self.view];for(MASConstraint*constraintininstalledConstraints){[constraint uninstall];}}NSArray*constraints=self.constraints.copy;for(MASConstraint*constraintinconstraints){constraint.updateExisting=self.updateExisting;[constraint install];}[self.constraints removeAllObjects];returnconstraints;}

其中最上面的那个判断条件在调用mas_remakeConstraints:方法时会被执行到,咋们也不看。咋们看下面这一段,其实self.constraints数组 就是在mas_makeConstraints:的 block 块中添加的所有约束对象,接下来 self.constraints 执行 copy 并遍历执行constraint.updateExisting = self.updateExisting;和[constraint install];,for 循环体中的第一句是标记更新约束还是新添加的约束,第二句是对约束装载,如果把第二句给注视掉,则添加的所有约束都不会被添加上,各位可以试一试;在方法的最后 返回了constraints数组,这个数组里面装的是MASConstraint类对象,再回到上面mas_makeConstraints:方法中,最后的return [constraintMaker install];实际上就是返回另一个约束对象的数组,没问题把。咋们在调用mas_makeConstraints:方法时可以用一个数组来接收,没毛病。。看代码

UIView*superView=[[UIView alloc]init];superView.backgroundColor=UIColor.greenColor;[self.view addSubview:superView];NSArray<MASConstraint*>*constraints=[superView mas_makeConstraints:^(MASConstraintMaker*make){make.left.mas_offset(20);make.right.mas_offset(-20);make.top.mas_offset(100);}];

咋们在来看两个方法,mas_offset()/mas_equalTo(),这两个方法其实就是一个宏,点进去看源码如此

#definemas_equalTo(...)                equalTo(MASBoxValue((__VA_ARGS__)))#definemas_greaterThanOrEqualTo(...)    greaterThanOrEqualTo(MASBoxValue((__VA_ARGS__)))#definemas_lessThanOrEqualTo(...)      lessThanOrEqualTo(MASBoxValue((__VA_ARGS__)))#definemas_offset(...)                  valueOffset(MASBoxValue((__VA_ARGS__)))#ifdefMAS_SHORTHAND_GLOBALS#defineequalTo(...)                    mas_equalTo(__VA_ARGS__)#definegreaterThanOrEqualTo(...)        mas_greaterThanOrEqualTo(__VA_ARGS__)#definelessThanOrEqualTo(...)          mas_lessThanOrEqualTo(__VA_ARGS__)#defineoffset(...)                      mas_offset(__VA_ARGS__)#endif

mas_equalTo 对应 equalTo 方法,mas_offset 对应 valueOffset 方法,这两个其实就是 Block 执行体,返回是调用者对象(连式编程的标志性语法),这个对象也就是MASConstraint类对象。继续下去。篇幅有点长,这个知识点就到这里把。

约束的卸载uninstall,使用MASConstraint对象调用这个uninstall,就会把约束从对应的view上卸载掉;如下代码

UIView*superView=[[UIView alloc]init];superView.backgroundColor=UIColor.greenColor;[self.view addSubview:superView];NSArray<MASConstraint*>*constraints=[superView mas_makeConstraints:^(MASConstraintMaker*make){make.left.mas_offset(20);make.right.mas_offset(-20);make.top.mas_offset(100);}];//卸载约束for(MASConstraint*constraintinconstraints){[constraint uninstall];}

等价于

UIView*superView=[[UIViewalloc]init];superView.backgroundColor=UIColor.greenColor;[self.view addSubview:superView];__blockMASConstraint*top=nil;__blockMASConstraint*left=nil;__blockMASConstraint*right=nil;[superView mas_makeConstraints:^(MASConstraintMaker*make){left=make.left.mas_offset(20);right=make.right.mas_offset(-20);top=make.top.mas_offset(100);}];//卸载约束[leftuninstall];[rightuninstall];[top uninstall];

约束的装载install,使用MASConstraint对象调用这个install,就会把约束装载到对应的view上;如下代码

UIView*superView=[[UIView alloc]init];superView.backgroundColor=UIColor.greenColor;[self.view addSubview:superView];NSArray<MASConstraint*>*constraints=[superView mas_makeConstraints:^(MASConstraintMaker*make){make.left.mas_offset(20);make.right.mas_offset(-20);make.top.mas_offset(100);}];//装载约束//for (MASConstraint *constraint in constraints) {//  [constraint install];//}

等价于

UIView*superView=[[UIViewalloc]init];superView.backgroundColor=UIColor.greenColor;[self.view addSubview:superView];__blockMASConstraint*top=nil;__blockMASConstraint*left=nil;__blockMASConstraint*right=nil;[superView mas_makeConstraints:^(MASConstraintMaker*make){left=make.left.mas_offset(20);right=make.right.mas_offset(-20);top=make.top.mas_offset(100);}];//装载约束//[left install];//[right install];//[top install];

预备知识讲完了,开始完成功能

首先定义三个全局属性必须得用到的

@interfaceDemo2ViewController()@property(nonatomic,weak)UIView*superView;@property(nonatomic,weak)UIView*bottomView;@property(nonatomic,weak)MASConstraint*bottom;@end

写一个createDemo方法来实现案列, 并调用这个方法

-(void)viewDidLoad{[super viewDidLoad];[self createDemo];}-(void)createDemo{//...案例代码在这里实现}

创建superView,不给 superView 高度,高度通过他的子视图给撑起来

-(void)createDemo{UIView*superView=[[UIView alloc]init];superView.backgroundColor=UIColor.greenColor;[self.view addSubview:superView];[superView mas_makeConstraints:^(MASConstraintMaker*make){make.left.mas_equalTo(20);make.right.mas_equalTo(-20);make.top.mas_equalTo(100);}];}

创建一个添加按钮,没点击一下添加一个view在这个添加按钮下面

-(void)createDemo{/*。。。。*/UIButton*button=[[UIButton alloc]init];[button setTitle:@"增加"forState:UIControlStateNormal];button.backgroundColor=UIColor.redColor;[button addTarget:selfaction:@selector(action:)forControlEvents:UIControlEventTouchUpInside];[superView addSubview:button];[button mas_makeConstraints:^(MASConstraintMaker*make){make.left.mas_equalTo(10);make.top.mas_equalTo(10);make.right.mas_equalTo(-10);self.bottom=make.bottom.mas_equalTo(-10);//记录下这个约束对象make.height.equalTo(@(100));}];}

在superView的下方添加一个blueView,这个视图blueView的顶部始终距离superView的底部10

-(void)createDemo{/*。。。。*/UIView*blueView=[[UIView alloc]init];blueView.backgroundColor=UIColor.blueColor;[self.view addSubview:blueView];[blueView mas_makeConstraints:^(MASConstraintMaker*make){make.left.mas_equalTo(20);make.right.mas_equalTo(-20);make.top.mas_equalTo(superView.mas_bottom).mas_offset(10);make.height.mas_equalTo(@(100));}];}

把superView赋值给self.superView,把button赋值给self.bottomView

-(void)createDemo{/*。。。。*/self.superView=superView;self.bottomView=button;}

运行效果图如下

WechatIMG44.png

实现添加方法action:,就能实现动态撑大父视图了

staticintnum=0;-(void)action:(UIButton*)button{//卸载旧的底部约束[self.bottom uninstall];num+=1;YYLabel*view=[[YYLabel alloc]init];view.backgroundColor=UIColor.redColor;view.text=[NSString stringWithFormat:@"控件%d",num];view.textAlignment=NSTextAlignmentCenter;view.textVerticalAlignment=YYTextVerticalAlignmentCenter;[self.superView addSubview:view];//给新 view 添加约束[view mas_makeConstraints:^(MASConstraintMaker*make){make.left.mas_equalTo(self.superView.mas_left).offset(10);make.top.mas_equalTo(self.bottomView.mas_bottom).offset(10);make.right.mas_equalTo(self.superView.mas_right).offset(-10);//添加新的底部约束self.bottom=make.bottom.mas_equalTo(self.superView.mas_bottom).offset(-10);make.height.equalTo(@(100));}];self.bottomView=view;}

效果图如下

Jan-18-2019 17-10-11.gif

masonry 在 UIScrollView 中的运用

masonry + UIScrollView 通过两个示例,一个是水平方向,另一个垂直方向,这也是平常开发中会遇到的。在使用masonry对UIScrollView设置约束后,contentSize属性就不管用了,而需要通过masonry 的规则在scrollView中添加一个 contentView,其它的子视图全部添加到 contentView 上,让contentView来撑起UIScrollview的 contentSize。

水平方向滑动

第一步创建一个Scrollview

// 水平方向滚动视图UIScrollView*scrollView=[[UIScrollView alloc]init];scrollView.backgroundColor=UIColor.greenColor;scrollView.pagingEnabled=YES;[self.view addSubview:scrollView];//设置 Scrollview 的约束[scrollView mas_makeConstraints:^(MASConstraintMaker*make){make.top.mas_equalTo(self.view).offset(100);make.left.mas_equalTo(10);make.right.mas_equalTo(-10);make.bottom.mas_equalTo(-100);}];

创建一个 contentView 放到Scrollview上,并设置约束

// 设置scrollView的子视图,即过渡视图contentSizeUIView*contentView=[[UIView alloc]init];[scrollView addSubview:contentView];[contentView mas_makeConstraints:^(MASConstraintMaker*make){make.edges.mas_equalTo(scrollView);make.height.mas_equalTo(scrollView);}];

动态添加子视图到 contentView 上

UIView*previousView=nil;for(inti=0;i<10;i++){YYLabel*label=[[YYLabel alloc]init];label.textAlignment=NSTextAlignmentCenter;label.numberOfLines=2;label.backgroundColor=UIColor.redColor;label.text=[NSString stringWithFormat:@"水平方向\n第 %d 个视图",(i+1)];// 添加到父视图,并设置过渡视图中子视图的约束[contentView addSubview:label];[label mas_makeConstraints:^(MASConstraintMaker*make){make.top.equalTo(contentView).offset(20);make.bottom.equalTo(contentView).offset(-20);make.width.equalTo(scrollView).offset(-40);if(previousView){make.left.mas_equalTo(previousView.mas_right).offset(40);}else{make.left.mas_equalTo(20);}}];previousView=label;}

设置 contentView 的right约束,这个是很关键的位置

//设置将影响到scrollView的contentSize[contentView mas_makeConstraints:^(MASConstraintMaker*make){make.right.mas_equalTo(previousView.mas_right).offset(20);}];

运行结果如下

Jan-18-2019 17-52-54.gif

垂直方向滑动

垂直方向上跟水平方向上的实现方式大致相同,我就直接粘代码过来了

@interfaceDemo3ViewController()@property(nonatomic,weak)UIView*superView;@property(nonatomic,weak)UIView*bottomView;@property(nonatomic,weak)MASConstraint*bottom;@end@implementationDemo3ViewController-(void)viewDidLoad{[superviewDidLoad];[selfcreateDemo];}-(void)createDemo{UIScrollView*scrollView=[[UIScrollView alloc]init];scrollView.backgroundColor=UIColor.greenColor;[self.view addSubview:scrollView];[scrollView mas_makeConstraints:^(MASConstraintMaker*make){make.center.mas_equalTo(0);make.right.mas_equalTo(-10.0);make.height.mas_equalTo(self.view).offset(-100);}];UIView*superView=[[UIView alloc]init];superView.backgroundColor=UIColor.greenColor;[scrollView addSubview:superView];[superView mas_makeConstraints:^(MASConstraintMaker*make){make.edges.equalTo(scrollView).with.insets(UIEdgeInsetsZero);make.width.mas_equalTo(scrollView);}];UIButton*button=[[UIButton alloc]init];[button setTitle:@"增加"forState:UIControlStateNormal];button.backgroundColor=UIColor.redColor;[button addTarget:selfaction:@selector(action:)forControlEvents:UIControlEventTouchUpInside];[superView addSubview:button];[button mas_makeConstraints:^(MASConstraintMaker*make){make.left.right.mas_equalTo(0);make.height.mas_equalTo(100);make.top.mas_equalTo(20);}];self.superView=superView;self.bottomView=button;//设置 scrollview 的 contentSize[self.superView mas_makeConstraints:^(MASConstraintMaker*make){self.bottom=make.bottom.mas_equalTo(self.bottomView.mas_bottom);}];}staticintnum=0;-(void)action:(UIButton*)button{//取消底部约束[self.bottom uninstall];num+=1;YYLabel*view=[[YYLabel alloc]init];view.backgroundColor=UIColor.redColor;view.text=[NSString stringWithFormat:@"控件%d",num];view.textAlignment=NSTextAlignmentCenter;view.textVerticalAlignment=YYTextVerticalAlignmentCenter;[self.superView addSubview:view];//给新 view 添加约束[view mas_makeConstraints:^(MASConstraintMaker*make){make.left.mas_equalTo(self.superView).offset(20);make.right.mas_equalTo(self.superView).offset(-20);make.height.mas_equalTo(100);make.top.mas_equalTo(self.bottomView.mas_bottom).offset(20);}];//记录最下面的 viewself.bottomView=view;//设置新的 contentSize[self.superView mas_makeConstraints:^(MASConstraintMaker*make){self.bottom=make.bottom.mas_equalTo(self.bottomView.mas_bottom);}];}

结果如下

Jan-18-2019 18-04-42.gif

masonry 多列等宽

固定间距

masonry提供了实现多列等高API,指定 item 之间的间距,然后 item 的宽或者高动态变化

/**

*  distribute with fixed spacing

*

*  @param axisType    which axis to distribute items along

*  @param fixedSpacing the spacing between each item

*  @param leadSpacing  the spacing before the first item and the container

*  @param tailSpacing  the spacing after the last item and the container

*/-(void)mas_distributeViewsAlongAxis:(MASAxisType)axisType withFixedSpacing:(CGFloat)fixedSpacing leadSpacing:(CGFloat)leadSpacing tailSpacing:(CGFloat)tailSpacing;

用法如下

-(void)createDemo{NSMutableArray*views=[NSMutableArray array];for(NSInteger i=0;i<3;i++){YYLabel*item=[[YYLabel alloc]init];view.backgroundColor=UIColor.greenColor;view.textAlignment=NSTextAlignmentCenter;view.text=[NSString stringWithFormat:@"%ld",i];[views addObject:item];[self.view addSubview:item];}[views mas_makeConstraints:^(MASConstraintMaker*make){make.centerY.mas_equalTo(self.view);make.height.mas_equalTo(100);}];[views mas_distributeViewsAlongAxis:MASAxisTypeHorizontal                      withFixedSpacing:50leadSpacing:10tailSpacing:20];}

WechatIMG46.jpeg

固定 item 宽度

masonry提供了实现多列等高API,指定 item 宽度或者高度,然后 item 之间的间距动态变化,方法描述

/**

*  distribute with fixed item size

*

*  @param axisType        which axis to distribute items along

*  @param fixedItemLength the fixed length of each item

*  @param leadSpacing    the spacing before the first item and the container

*  @param tailSpacing    the spacing after the last item and the container

*/-(void)mas_distributeViewsAlongAxis:(MASAxisType)axisType withFixedItemLength:(CGFloat)fixedItemLength leadSpacing:(CGFloat)leadSpacing tailSpacing:(CGFloat)tailSpacing;

用法

-(void)createDemo{NSMutableArray*views=[NSMutableArray array];for(NSInteger i=0;i<3;i++){YYLabel*item=[[YYLabel alloc]init];item.backgroundColor=UIColor.greenColor;item.textAlignment=NSTextAlignmentCenter;item.text=[NSString stringWithFormat:@"%ld",i];[views addObject:item];[self.view addSubview:item];}[views mas_makeConstraints:^(MASConstraintMaker*make){make.centerY.mas_equalTo(self.view);make.height.mas_equalTo(100);}];[views mas_distributeViewsAlongAxis:MASAxisTypeHorizontal                    withFixedItemLength:100leadSpacing:50tailSpacing:50];}

WechatIMG47.jpeg

masonry 设置宽高比例

在 masonry 提供了multipliedBy()函数用来处理布局比例问题

,API

/**

*  Sets the NSLayoutConstraint multiplier property

*/-(MASConstraint*(^)(CGFloat multiplier))multipliedBy;

用法

-(void)createDemo{//示例1YYLabel*superView=[[YYLabel alloc]init];superView.text=@"示例2";superView.textAlignment=NSTextAlignmentCenter;superView.backgroundColor=UIColor.redColor;[self.view addSubview:superView];[superView mas_makeConstraints:^(MASConstraintMaker*make){make.center.mas_equalTo(0);//superView.width = superView.height = self.view.width * 0.5;make.width.height.mas_equalTo(self.view.mas_width).multipliedBy(0.5);}];//示例2YYLabel*subView=[[YYLabel alloc]init];subView.text=@"示例2";subView.textAlignment=NSTextAlignmentCenter;subView.backgroundColor=UIColor.blueColor;[superView addSubview:subView];[subView mas_makeConstraints:^(MASConstraintMaker*make){make.center.mas_equalTo(0);make.width.mas_equalTo(superView);//subView.height = subView.width * 0.5;make.height.mas_equalTo(subView.mas_width).multipliedBy(0.5);}];}

运行结果如下

WechatIMG48.jpeg

masonry UIButton 自适应宽度

在 UIButton 自使用中需要使用到 mas_greaterThanOrEqualTo(value) 以及 mas_lessThanOrEqualTo(value)方法,mas_greaterThanOrEqualTo(value) 大于等于 value,mas_lessThanOrEqualTo(value)则是小于等于value

示例如下

UIButton*btn=[[UIButton alloc]init];btn.backgroundColor=[UIColor blueColor];[btn setTitle:@"UIButton宽度"forState:UIControlStateNormal];[btn setImage:[UIImage imageNamed:@"icon"]forState:UIControlStateNormal];[btn addTarget:selfaction:@selector(clicked:)forControlEvents:UIControlEventTouchUpInside];[self.view addSubview:btn];[btn mas_makeConstraints:^(MASConstraintMaker*make){make.center.mas_equalTo(self.view);make.height.mas_equalTo(@[btn.titleLabel.mas_height,btn.imageView.mas_height]);make.width.mas_lessThanOrEqualTo(kScreenWidth);}];

clicked:方法实现

-(void)clicked:(UIButton*)btn{[btn setTitle:[btn.currentTitle stringByAppendingString:@"自适应"]forState:UIControlStateNormal];}

看看效果怎么样

Jan-18-2019 20-06-16.gif

UIButton 还有很多玩法,这里就不一一举例了

masonry UILabel 自适应宽度/高度

对于 UILabel 自适应宽度只需要使用mas_lessThanOrEqualTo()方法就能达到

当宽度达到极限后开始换行需要设置两个参数,UILabel的 numberOfLines 属性和 preferredMaxLayoutWidth 属性,

代码实现

//普通文本-(void)createDemo{self.label2=[[UILabel alloc]init];self.label2.tag=100;[self.view addSubview:self.label2];self.label2.text=@"最近是用Masonry";self.label2.backgroundColor=UIColor.redColor;[self.label2 setPreferredMaxLayoutWidth:self.view.width-30];self.label2.numberOfLines=0;[self.label2 setContentHuggingPriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisVertical];[self.label2 mas_makeConstraints:^(MASConstraintMaker*make){make.top.mas_equalTo(100);make.left.mas_equalTo(15);}];UIButton*btn=[[UIButton alloc]init];btn.backgroundColor=[UIColor blueColor];[btn setTitle:@"添加文字"forState:UIControlStateNormal];[btn addTarget:selfaction:@selector(clicked)forControlEvents:UIControlEventTouchUpInside];[self.view addSubview:btn];[btn mas_makeConstraints:^(MASConstraintMaker*make){make.top.mas_equalTo(self.label2.mas_bottom).mas_offset(20);make.centerX.mas_equalTo(self.view);make.height.mas_equalTo(50);make.width.mas_lessThanOrEqualTo(kScreenWidth);}];}-(void)clicked{self.label2.text=[self.label2.text stringByAppendingString:@"Masonry自动布局UILabel"];}

结果如下

Jan-18-2019 20-57-21.gif

masonry YYLabel 自适应宽度/高度

代码实现

-(void)createDemo{self.label1=[[YYLabel alloc]init];self.label1.text=@"最近是用Masonry自动布局UILabel的时候,;这些东西之后,label还是没有换行。最近是用Masonry自动布局UILabel的时候,";self.label1.backgroundColor=UIColor.greenColor;self.label1.numberOfLines=0;self.label1.preferredMaxLayoutWidth=self.view.width-30;[self.view addSubview:self.label1];[self.label1 mas_makeConstraints:^(MASConstraintMaker*make){make.top.mas_equalTo(100);make.left.mas_equalTo(15);}];UIButton*btn=[[UIButton alloc]init];btn.backgroundColor=[UIColor blueColor];[btn setTitle:@"添加文字"forState:UIControlStateNormal];[btn addTarget:selfaction:@selector(clicked)forControlEvents:UIControlEventTouchUpInside];[self.view addSubview:btn];[btn mas_makeConstraints:^(MASConstraintMaker*make){make.top.mas_equalTo(self.label1.mas_bottom).mas_offset(20);make.centerX.mas_equalTo(self.view);make.height.mas_equalTo(50);make.width.mas_lessThanOrEqualTo(kScreenWidth);}];}-(void)clicked{self.label1.text=[self.label1.text stringByAppendingString:@"Masonry自动布局YYLabel"];}

结果如下

Jan-18-2019 20-43-44.gif

masonry 实现动态 UITabelViewCell

先看效果

Jan-18-2019 21-03-23.gif

demo实现得很粗糙,但是基本功能都实现了。实现动态 UITabelViewCell 需要了解到的知识点

不设置cell的高度

不实现返回cell高度的代理方法

设置 UITabelViewCell的estimatedRowHeight属性

将tableview的rowHeight属性设置为UITableViewAutomaticDimension

示例如下

-(UITableView*)tableView{if(!_tableView){_tableView=[[UITableView alloc]initWithFrame:CGRectZero style:UITableViewStylePlain];_tableView.delegate=self;_tableView.dataSource=self;_tableView.estimatedRowHeight=100;_tableView.rowHeight=UITableViewAutomaticDimension;[_tableView registerClass:Demo8Cell.class forCellReuseIdentifier:@"cellID"];[self.view addSubview:_tableView];}return_tableView;}

关于 tableview 需要设置的就这些,剩下的在 tableviewCell 的动态高度在cell内部设置

关于 Demo8Cell 内部实现如下

.h

@classDemo8Model;NS_ASSUME_NONNULL_BEGIN@interfaceDemo8Cell:UITableViewCell@property(nonatomic,strong)UILabel*messageLabel;-(void)setmessage:(Demo8Model*)message;@end

.m

@interfaceDemo8Cell()@property(nonatomic,strong)UIView*picContentView;@property(nonatomic,strong)UIView*timerView;@property(nonatomic,strong)UIView*likeView;@end@implementationDemo8Cell-(instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString*)reuseIdentifier{if(self=[superinitWithStyle:style reuseIdentifier:reuseIdentifier]){[selfcreateUI];}returnself;}-(void)createUI{self.messageLabel=[[UILabel alloc]init];self.messageLabel.numberOfLines=0;[self.contentView addSubview:self.messageLabel];[self.messageLabel mas_makeConstraints:^(MASConstraintMaker*make){make.top.mas_equalTo(8);make.left.mas_equalTo(10);make.right.mas_equalTo(-10);}];self.picContentView=[[UIView alloc]init];self.picContentView.backgroundColor=UIColor.grayColor;[self.contentView addSubview:self.picContentView];[self.picContentView mas_makeConstraints:^(MASConstraintMaker*make){make.top.mas_equalTo(self.messageLabel.mas_bottom).offset(15);make.left.mas_offset(50);make.right.mas_offset(-20);}];self.timerView=[[UIView alloc]init];self.timerView.backgroundColor=UIColor.redColor;[self.contentView addSubview:self.timerView];[self.timerView mas_makeConstraints:^(MASConstraintMaker*make){make.top.mas_equalTo(self.picContentView.mas_bottom).mas_offset(10);make.left.mas_equalTo(50);make.height.mas_equalTo(30);make.width.mas_equalTo(50);//关键位置make.bottom.mas_equalTo(-8);}];self.likeView=[[UIView alloc]init];self.likeView.backgroundColor=UIColor.redColor;[self.contentView addSubview:self.likeView];[self.likeView mas_makeConstraints:^(MASConstraintMaker*make){make.top.mas_equalTo(self.picContentView.mas_bottom).mas_offset(10);make.right.mas_equalTo(-20);make.height.mas_equalTo(30);make.width.mas_equalTo(50);}];}-(void)setmessage:(Demo8Model*)message{// 创建一个可变属性字符串NSMutableAttributedString*finalStr=[[NSMutableAttributedString alloc]init];// 创建姓名NSAttributedString*nameStr=[[NSAttributedString alloc]initWithString:message.name attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:16],NSForegroundColorAttributeName:[UIColor redColor]}];// 创建发言内容NSAttributedString*messageStr=[[NSAttributedString alloc]initWithString:message.message attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:16],NSForegroundColorAttributeName:[UIColor blackColor]}];// 拼接上两个字符串[finalStr appendAttributedString:nameStr];[finalStr appendAttributedString:messageStr];self.messageLabel.attributedText=finalStr;//移除所有图片[self.picContentView removeAllSubviews];[selfcreateDemo:message.picNum];}-(void)createDemo:(NSInteger)itemNum{//假设要显示 num 个itemNSInteger num=itemNum;//每行显示的个数NSInteger count=3;//显示的总行数NSInteger rowNum=(num/count)+((NSInteger)(num%count>0));UIView*lastView=nil;for(inti=0;i<rowNum;i++){NSMutableArray*masonryViewArray=[NSMutableArray array];for(intj=0;j<count;j++){UIView*view=[[UIView alloc]init];if((i*count)+j>num-1){view.backgroundColor=[UIColor clearColor];}else{view.backgroundColor=[UIColor redColor];}[self.picContentView addSubview:view];[masonryViewArray addObject:view];lastView=view;}// 固定 item 之间的间距,item 的宽或者高自动缩放[masonryViewArray mas_distributeViewsAlongAxis:MASAxisTypeHorizontal withFixedSpacing:30leadSpacing:10tailSpacing:10];// 设置array的垂直方向的约束[masonryViewArray mas_makeConstraints:^(MASConstraintMaker*make){make.top.equalTo(@((100*i)+10));make.height.equalTo(@80);}];}if(lastView){[self.picContentView mas_makeConstraints:^(MASConstraintMaker*make){make.bottom.mas_equalTo(lastView.mas_bottom).mas_offset(20);}];}}@end

未完待续。。。。

作者:朽木自雕也

链接:https://www.jianshu.com/p/fba79bcc10e1

来源:简书

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

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

推荐阅读更多精彩内容