如何使用masonry设计复合型cell[转]
前言
其实早在@sunnyxx同学发布UIView-FDCollapsibleConstraints的时候 我就说要写一下怎么用代码来稍微麻烦的实现复用的问题 但是一直各种没时间(主要是我的办法太复杂 - -) 正好看到@叶孤城同学也说了一下他的解决办法 所以我来说一下我是如何解决这个问题的
分析
我们以叶孤城同学的例子来简单分析一下 假设view是这样的(为了方便 将所有的间隙设定为20)
正常的布局是这样的

布局代码如下:
interface ComplexCell()
@property (nonatomic, strong) UIView *vB; //view blue height:30
@property (nonatomic, strong) UIView *vY; //view yellow height:30
@property (nonatomic, strong) UIView *vR; //view red height:30
@property (nonatomic, strong) UIView *vG; //view green height:100
@end
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; if ( self ) { CGFloat spacing = 20.0f; self.vB = [UIView new];
[self.contentView addSubview:self.vB];
[self.vB mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.top.equalTo(self.contentView).insets(UIEdgeInsetsMake(spacing,spacing,,));
make.width.equalTo(@);
make.height.equalTo(@).priorityLow();
self.cB = make.height.equalTo(@).priority(UILayoutPriorityRequired);
}];
self.vB.backgroundColor = [UIColor blueColor]; self.vY = [UIView new];
[self.contentView addSubview:self.vY];
[self.vY mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(self.vB.mas_right).offset(spacing);
make.right.top.equalTo(self.contentView).insets(UIEdgeInsetsMake(spacing,,,spacing));
make.height.equalTo(@).priorityLow();
self.cY = make.height.equalTo(@).priority(UILayoutPriorityRequired);
}];
self.vY.backgroundColor = [UIColor yellowColor]; self.vR = [UIView new];
[self.contentView addSubview:self.vR];
[self.vR mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.vB.mas_bottom).offset(spacing);
make.left.right.equalTo(self.contentView).insets(UIEdgeInsetsMake(,spacing,,spacing));
make.height.equalTo(@).priorityLow();
self.cR = make.height.equalTo(@).priority(UILayoutPriorityRequired);
}];
self.vR.backgroundColor = [UIColor redColor]; self.vG = [UIView new];
[self.contentView addSubview:self.vG];
[self.vG mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.vR.mas_bottom).offset(spacing);
make.left.right.equalTo(self.contentView).insets(UIEdgeInsetsMake(,spacing,,spacing));
make.height.equalTo(@).priorityLow();
self.cG = make.height.equalTo(@).priority(UILayoutPriorityRequired);
}];
self.vG.backgroundColor = [UIColor greenColor]; } return self;
实际效果如图

看上去还不错
在Masonry中 针对单条的MASLayoutConstraint可以进行active和deactive操作 那么意味着可以动态的启用或者禁用某条预置的约束 所以我们只要预先设置一条高优先级的高度为0(或者宽度为0)的约束 然后在适当的时候激活它不就行了? 先尝试隐藏红色的view 隐藏后如下

啊~哦~ 结果不正确 隐藏是隐藏了 但是间隙没有隐藏 导致缝变大了 这是因为我们仅仅隐藏了view 而没有隐藏view之间的间隔 那么应该如何处理这种情况呢?
主流的做法是将这个view的所有约束值全设置成0 然后恢复的时候再还原 这种方法需要记录原值 但是在前言我说了 要用稍微麻烦的方法来解决这个问题 所以肯定不是这样做啦
我采用的方法是group法 具体如下图

其实在第一行还有一个groupview如图

但是因为图显示出来不太好看(不会画图 T_T ) 所以我隐藏了 具体可以看代码细节
每个(或者每组)可以隐藏的view 都对应有一个group view(group其实就是包含了view和spacing) 需要隐藏的时候 直接隐藏这个group 就可以达到既隐藏view又缩短间隙的目的
代码较长 大家可以选择跳过 - -!
@interface ComplexCell()
@property (nonatomic, strong) MASConstraint *cF; //constraint first row
@property (nonatomic, strong) MASConstraint *cB; //constraint blue
@property (nonatomic, strong) MASConstraint *cY; //constraint yellow
@property (nonatomic, strong) MASConstraint *cR; //constraint red
@property (nonatomic, strong) MASConstraint *cG; //constraint green
@property (nonatomic, strong) UIView *gF; //group first row
@property (nonatomic, strong) UIView *gB; //group blue
@property (nonatomic, strong) UIView *gY; //group yellow
@property (nonatomic, strong) UIView *gR; //group red
@property (nonatomic, strong) UIView *gG; //group green
@property (nonatomic, strong) UIView *vB; //view blue height:30
@property (nonatomic, strong) UIView *vY; //view yellow height:30
@property (nonatomic, strong) UIView *vR; //view red height:30
@property (nonatomic, strong) UIView *vG; //view green height:100
@end
@implementation ComplexCell
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; if ( self ) { CGFloat spacing = 20.0f; self.gF = [UIView new];
[self.contentView addSubview:self.gF];
[self.gF mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.top.right.equalTo(self.contentView); self.cF = make.height.equalTo(@).priority(UILayoutPriorityRequired);
[self.cF deactivate];
}];
self.gF.clipsToBounds = YES; self.gB = [UIView new];
[self.gF addSubview:self.gB];
[self.gB mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.top.bottom.equalTo(self.gF); self.cB = make.width.equalTo(@).priority(UILayoutPriorityRequired);
[self.cB deactivate];
}];
self.gB.clipsToBounds = YES; self.gY = [UIView new];
[self.gF addSubview:self.gY];
[self.gY mas_makeConstraints:^(MASConstraintMaker *make) {
make.right.top.bottom.equalTo(self.gF);
make.left.equalTo(self.gB.mas_right); self.cY = make.width.equalTo(@).priority(UILayoutPriorityRequired);
[self.cY deactivate];
}];
self.gY.clipsToBounds = YES; self.gR = [UIView new];
[self.contentView addSubview:self.gR];
[self.gR mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.right.equalTo(self.contentView);
make.top.equalTo(self.gF.mas_bottom); self.cR = make.height.equalTo(@).priority(UILayoutPriorityRequired);
[self.cR deactivate];
}];
self.gR.clipsToBounds = YES; self.gG = [UIView new];
[self.contentView addSubview:self.gG];
[self.gG mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.right.equalTo(self.contentView);
make.top.equalTo(self.gR.mas_bottom); self.cG = make.height.equalTo(@).priority(UILayoutPriorityRequired);
[self.cG deactivate];
}];
self.gG.clipsToBounds = YES; self.vB = [UIView new];
[self.gB addSubview:self.vB];
[self.vB mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(self.gB).insets(UIEdgeInsetsMake(spacing, spacing, , )).priorityLow();
make.height.equalTo(@);
make.width.equalTo(@);
}];
self.vB.backgroundColor = [UIColor blueColor]; self.vY = [UIView new];
[self.gY addSubview:self.vY];
[self.vY mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(self.gY).insets(UIEdgeInsetsMake(spacing, spacing, , spacing)).priorityLow();
make.height.equalTo(@);
}];
self.vY.backgroundColor = [UIColor yellowColor]; self.vR = [UIView new];
[self.gR addSubview:self.vR];
[self.vR mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(self.gR).insets(UIEdgeInsetsMake(spacing, spacing, , spacing)).priorityLow();
make.height.equalTo(@);
}];
self.vR.backgroundColor = [UIColor redColor]; self.vG = [UIView new];
[self.gG addSubview:self.vG];
[self.vG mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(self.gG).insets(UIEdgeInsetsMake(spacing, spacing, , spacing)).priorityLow();
make.height.equalTo(@);
}];
self.vG.backgroundColor = [UIColor greenColor]; } return self;
}
然后 为每种不同的布局定义一个枚举(为了举例我随便定义的 0和1代表这个view是否被显示)
typedef NS_ENUM(NSUInteger, ComplexType) {
ComplexType1111,
ComplexType1110,
ComplexType0111,
ComplexType0011,
ComplexType0010,
ComplexType1101
};
@interface ComplexCell : UITableViewCell
@property (nonatomic, assign) ComplexType type;
@end
- (void)setType:(ComplexType)type {
[self.cF deactivate];
[self.cB deactivate];
[self.cY deactivate];
[self.cR deactivate];
[self.cG deactivate];
switch (type) {
case ComplexType1111:
{
break;
}
case ComplexType0111:
{
[self.cB activate];
break;
}
case ComplexType0011:
{
[self.cF activate];
break;
}
case ComplexType1110:
{
[self.cG activate];
break;
}
case ComplexType1101:
{
[self.cR activate];
break;
}
case ComplexType0010:
{
[self.cF activate];
[self.cG activate];
break;
}
default:
break;
}
}
这样 在tableview的datasource中我们只要这样做就可以了
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return ;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return ;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
return [ComplexCell getHeightByType:indexPath.row%];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
ComplexCell* cell = [tableView dequeueReusableCellWithIdentifier:@"cell"];
cell.type = indexPath.row%;
return cell;
}
看看效果 是不是很不错






小结
文中的demo可以在这里找到 要注意的地方是约束的priority的设置 另外 这种方式也支持不定长内容的Autolayout
可能很多人看了觉得我在瞎折腾 明明一个挺简单实现的东西 被我一弄 弄得又长又臭 其实不然 像我这种方法虽然麻烦了点(文章开头就指出了) 但是面对稍微复杂点的需求 却是更得心应手(其实有点类似DIV+CSS的感觉有木有?)
使用group的方式 面对同时在横向和纵向都有隐藏要求的时候 会方便很多
比如文中举的例子 第一行有时会隐藏蓝色的按钮 有时整个一行都会不显示 这样的话 当我想隐藏按钮时 只要激活按钮的约束 想隐藏整行时 只要激活整行的那条约束就行了
from:http://adad184.com/2015/06/08/complex-cell-with-masonry/
如何使用masonry设计复合型cell[转]的更多相关文章
- Masonry
Autolayout就像一个知情达理,善解人意的好姑娘,可惜长相有点不堪入目,所以追求者寥寥无几.所幸遇到了化妆大师cloudkite,给她来了一个完美的化妆,从此丑小鸭Autolayout变成了美天 ...
- Tumblr 架构设计
英文原文:The Tumblr Architecture Yahoo Bought For A Cool Billion Dollars 最近的新闻中我们得知雅虎11亿美元收购了Tumblr: Yah ...
- iOS开发——高级UI&带你玩转UITableView
带你玩装UITableView 在实际iOS开发中UITableView是使用最多,也是最重要的一个控件,如果你不会用它,那别说什么大神了,菜鸟都不如. 其实关于UItableView事非常简单的,实 ...
- Cocoapods的使用教程
前言 对于iOS App的开发,几乎都采用了Cocoapods来管理第三方库,那么对于我们开发人员来说,这是必备技能,必须要掌握如何使用.这篇文章就是介绍如何安装和使用CocoaPods的. 这篇文章 ...
- iOS 父子关系
1.面向对象特征,类的继承 成员变量(实例变量) 子类继承父类所有功能,只能直接(访问)调用父类中的.h中的protect和public成员变量(实例变量)及方法, .h中的私有的成员变量,子类不能直 ...
- [iOS基础控件 - 6.6] 展示团购数据 自定义TableViewCell
A.需求 1.头部广告 2.自定义cell:含有图片.名称.购买数量.价格 3.使用xib设计自定义cell,自定义cell继承自UITableViewCell 4.尾部“加载更多按钮”,以及其被点击 ...
- Swift - 使用网格(UICollectionView)进行流布局
一.网格UICollectionView最典型的例子是iBooks.其主要属性如下: 1,layout 该属性表示布局方式,有Flow.Custom两种布局方式.默认是Flow流式布局. 2,Acce ...
- iOS开源加密相册Agony的实现(四)
简介 虽然目前市面上有一些不错的加密相册App,但不是内置广告,就是对上传的张数有所限制.本文介绍了一个加密相册的制作过程,该加密相册将包括多密码(输入不同的密码即可访问不同的空间,可掩人耳目).Wi ...
- android开发(3):列表listview的实现 | 下拉刷新
APP里面的列表太常用了,系统提供的listview或grideview可以做到.另外,我希望这个列表能够下拉时触发刷新,于是考虑使用封装了这个功能的开源项目,这里介绍这个: https://gith ...
随机推荐
- iKcamp|基于Koa2搭建Node.js实战(含视频)☞ 解析JSON
视频地址:https://www.cctalk.com/v/15114923886141 JSON 数据 我颠倒了整个世界,只为摆正你的倒影. 前面的文章中,我们已经完成了项目中常见的问题,比如 路由 ...
- Javascript系列:总体理解
js是一个脚本客户端(浏览器)语言.和sql html类似.多练习. 没有排错的经验,弱类型语言,浏览器解释执行,出错也不会报错 预备 <!DOCTYPE html PUBLIC "- ...
- Linux运维就业技术指导(八):期中架构考核
一,期中架构考核概述 1.1 架构图 1.2 架构图公司背景概述 公司是一个新兴的人脸识别高新创业公司,公司名称xxxx 老总是博士生导师,还有一个副总是研究生导师 副总同时是研发总监,负责所有的研发 ...
- hadoop 官方配置文件解析
比如我的版本是2.8.4 官网文档是: http://hadoop.apache.org/docs/r2.8.4/ 基本配置文件:包括一般的端口 hdfs-default.xml dfs.nameno ...
- android热门消息推送横向测评![转]
关于这个话题,已经不是什么新鲜事了.对于大多数中小型公司一般都是选择第三方的服务来实现.但是现在已经有很多提供推送服务的公司和产品,如何选择一个适合自己项目的服务呢?它们之间都有什么差别?在此为大家做 ...
- MYSQL 备份及还原数据库
二.还原 1.NEW DB
- for循环计算阶乘
int x = 10; for(int y = x - 1; y >= 1; y--) { x = x * y; } System.out.println(x); 从10乘到1的阶乘写法. lo ...
- linux分区之gpt(大于2T的分区)
1.文件系统限制: ext3块尺寸 最大文件尺寸 最大文件系统尺寸1KiB 16GiB 2TiB2KiB 256GiB 8TiB4KiB 2TiB 16TiB8KiB 16TiB 32 ...
- 关于空指针NULL、野指针、通用指针
http://www.cnblogs.com/losesea/archive/2012/11/16/2772590.html 首先说一下什么是指针,只要明白了指针的含义,你就明白null的含义了.假设 ...
- mongo远程登录
1. 进入数据库: use admin db.addUser("foo","foo"); ps:高版本用db.createUser创建. 2. 改配置 如/et ...