哈喽,我是二西,我又来了,今天来记录下Masonry的几个妙用,希望能帮到你们
日常推歌,燃燃燃~
踏山河 music.163.com/#/song?id=1…
自适应拉伸布局
你们是否遇到过这样的布局,前面一张固定大小的图片,中间一个长短不固定昵称,后面有紧贴着昵称的小图标,然后最后还有一个靠右的固定大小图片。这种布局的难点在哪里呢?昵称如果短没啥问题,但是一旦昵称很长,后面的图标有可能就重叠,也有可能直接超出屏幕外面,是不是是不是。好了,我这里提供一个解决方案,如果有更好的方案欢迎评论区提出来~
上代码
//头像
UIImageView *headImageV = [[UIImageView alloc] init];
//昵称
UILabel *nicknameL = [[UILabel alloc] init];
//图标1
UIImageView *icon1V = [[UIImageView alloc] init];
//图标2
UIImageView *icon2V = [[UIImageView alloc] init];
//关注
UIButton *followBtn = [UIButton buttonWithType:UIButtonTypeCustom];
[self.view addSubview:headImageV];
[self.view addSubview:nicknameL];
[self.view addSubview:icon1V];
[self.view addSubview:icon2V];
[self.view addSubview:followBtn];
[headImageV mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.mas_equalTo(16);
make.top.mas_equalTo(16);
make.size.mas_equalTo(CGSizeMake(40, 40));
}];
[nicknameL mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.mas_equalTo(headImageV.mas_right).mas_offset(10);
make.top.mas_equalTo(20);
}];
[icon1V mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.mas_equalTo(nicknameL.mas_right).mas_offset(6);
make.centerY.mas_equalTo(nicknameL);
make.size.mas_equalTo(CGSizeMake(16, 16));
}];
[icon2V mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.mas_equalTo(icon1V.mas_right).mas_offset(6);
make.centerY.mas_equalTo(nicknameL);;
make.size.mas_equalTo(CGSizeMake(16, 16));
}];
[followBtn mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.mas_equalTo(icon2V.mas_right).mas_offset(10).priorityHigh();//重点1
make.centerY.mas_equalTo(headImageV);
make.right.mas_equalTo(16);
}];
//重点2
[headImageV setContentHuggingPriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisHorizontal];
[headImageV setContentCompressionResistancePriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisHorizontal];
[nicknameL setContentHuggingPriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisHorizontal];
[nicknameL setContentCompressionResistancePriority:UILayoutPriorityDefaultLow forAxis:UILayoutConstraintAxisHorizontal];
[icon1V setContentHuggingPriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisHorizontal];
[icon1V setContentCompressionResistancePriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisHorizontal];
[icon2V setContentHuggingPriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisHorizontal];
[icon2V setContentCompressionResistancePriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisHorizontal];
[followBtn setContentHuggingPriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisHorizontal];
[followBtn setContentCompressionResistancePriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisHorizontal];
复制代码
重点1这里,要设置
priorityHigh()
,这个属性可以设置两个控件之间约束的优先级,解决约束冲突,可以使控件之间留有空白
重点2这里,有两个方法,
setContentHuggingPriority
(抗拉伸),setContentCompressionResistancePriority
(抗压缩),这两个方法主要用途是这样的,比如,水平方向有两个控件,两个控件约束铺满水平,但是控件内容并没有达到,这时候,应该优先拉伸哪个控件呢,就是靠这个setContentHuggingPriority来判断,反之,如果两个控件内容加起来超过一行,这时候又要压缩哪个控件的内容呢,就是靠setContentCompressionResistancePriority来判断了。理解起来可能有点难,建议度娘谷哥食用哈哈哈
评论区新写法
感谢 @DTL432591:
重点1这里改为 make.left.mas_greaterThanOrEqualTo(icon2V.mas_right).mas_offset(10);
重点2只需设置nicknameL的抗压缩属性 [nicknameL setContentCompressionResistancePriority:UILayoutPriorityDefaultLow forAxis:UILayoutConstraintAxisHorizontal];
我试了下是可以实现的这种需求的,原理差不多,通过mas_greaterThanOrEqualTo产生一定空隙,再设置控件的抗压缩低优先级,防止过长时挤压其他控件。这代码理解起来可能比较容易,推荐大家尝试尝试,有问题我们在讨论讨论哈~
UIScrollView布局
用Masonry来布局UIScrollView,直接对scrollView进行约束是不行的,我这边的方案是通过一个中间view来充当容器,用这个容器大小来撑开scrollView,这个view的大小实际上就是contentSize。当然啦,依旧欢迎大家的方案,评论区见~
UIScrollView *scrollView = [[UIScrollView alloc] init];
UIView *contentV = [[UIView alloc] init];
UIView *firstV = [[UIView alloc] init];
UIView *secondV = [[UIView alloc] init];
[scrollView addSubview:contentV];
[contentV addSubview:firstV];
[contentV addSubview:secondV];
[contentV mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.mas_equalTo(scrollView);
make.height.mas_equalTo(100);
}];
[firstV mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.bottom.mas_equalTo(0);
make.left.mas_equalTo(16);//内容左约束
make.width.mas_equalTo(100);
}];
[secondV mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.bottom.mas_equalTo(0);
make.left.mas_equalTo(firstV.mas_right).mas_offset(10);
make.right.mas_equalTo(-16);//内容右约束
make.width.mas_equalTo(100);
}];
复制代码
有个问题说下,这种方案实际上就是靠contentV上添加的view左右约束来撑开contentV,使contentV有宽度,scrollView就可以滑动啦。当然,你也可以直接给contentV设置一个width约束,这样也可以滑动
Masonry动画
Masonry改变约束支持动画
UIView *view = [[UIView alloc] init];
[self.view addSubview:view];
[view mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.mas_equalTo(100);
make.left.right.mas_equalTo(0);
make.height.mas_equalTo(50);
}];
//支持动画
[self.view layoutIfNeeded];
[UIView animateWithDuration:0.3 animations:^{
[view mas_updateConstraints:^(MASConstraintMaker *make) {
make.top.mas_equalTo(400);
}];
[self.view layoutIfNeeded];
}];
复制代码
做动画一定要记得进行父控件
layoutIfNeeded
刷新下约束,不然没效果。而外说一句,这个方法可以马上刷新布局,得到控件frame数值
最后
暂时只能想到这几个,大家还有没有Masonry其他的特别用法,有的话欢迎评论区提出来啦啦啦~~~