为什么要做这个笔记
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
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。