如何使用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,0,0));
            make.width.equalTo(@60);
            make.height.equalTo(@30).priorityLow();
            self.cB = make.height.equalTo(@0).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,0,0,spacing));
            make.height.equalTo(@30).priorityLow();
            self.cY = make.height.equalTo(@0).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(0,spacing,0,spacing));
            make.height.equalTo(@30).priorityLow();
            self.cR = make.height.equalTo(@0).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(0,spacing,0,spacing));
            make.height.equalTo(@100).priorityLow();
            self.cG = make.height.equalTo(@0).priority(UILayoutPriorityRequired);
        }];
        self.vG.backgroundColor = [UIColor greenColor];

    }

    return self;

实际效果如图

看上去还不错

在Masonry中 针对单条的MASLayoutConstraint可以进行activedeactive操作 那么意味着可以动态的启用或者禁用某条预置的约束 所以我们只要预先设置一条高优先级的高度为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(@0).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(@0).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(@0).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(@0).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(@0).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, 0, 0)).priorityLow();
            make.height.equalTo(@30);
            make.width.equalTo(@60);
        }];
        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, 0, spacing)).priorityLow();
            make.height.equalTo(@30);
        }];
        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, 0, spacing)).priorityLow();
            make.height.equalTo(@30);
        }];
        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, 0, spacing)).priorityLow();
            make.height.equalTo(@100);
        }];
        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 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return 6;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    return [ComplexCell getHeightByType:indexPath.row%6];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    ComplexCell* cell = [tableView dequeueReusableCellWithIdentifier:@"cell"];
    cell.type = indexPath.row%6;

    return cell;
}

看看效果 是不是很不错

小结

文中的demo可以在这里找到 要注意的地方是约束的priority的设置 另外 这种方式也支持不定长内容的Autolayout

可能很多人看了觉得我在瞎折腾 明明一个挺简单实现的东西 被我一弄 弄得又长又臭 其实不然 像我这种方法虽然麻烦了点(文章开头就指出了) 但是面对稍微复杂点的需求 却是更得心应手(其实有点类似DIV+CSS的感觉有木有?)

使用group的方式 面对同时在横向和纵向都有隐藏要求的时候 会方便很多

比如文中举的例子 第一行有时会隐藏蓝色的按钮 有时整个一行都会不显示 这样的话 当我想隐藏按钮时 只要激活按钮的约束 想隐藏整行时 只要激活整行的那条约束就行了

from:http://adad184.com/2015/06/08/complex-cell-with-masonry/

时间: 2024-10-05 12:18:10

如何使用masonry设计复合型cell[转]的相关文章

AutoLayout -Masonry

History and Something Insteresting 手写代码的UI的自动布局在iOS6中引入的新特性iOS 6 brings an awesome new feature to the iPhone and iPad: Auto Layout, 以取代之前的 autoresizingMask( "springs and struts" Model). 实际上关于纯手写代码UI Layout经历了三个时期,固定宽高(这个用frame设计非常容易),Autoresizin

iOS 如何设置tableview列表的cell上的的设置删除键 、置顶按钮、 未读信息按钮

思路很重要! 主要是写下我实现的具体思想,效果:首先,将cell向左滑动的时候,就会出现 删除  置顶 等按钮,那么我们就可以设计在cell上加两层的控件,第一层放的便是你要添加的 删除  置顶 等按钮  ,把这些按钮布置在cell的右侧  然后在第二层就是放一个uiview 这个uiview大小和cell的大小一样  然后再到uiview上添加一些显示数据的控件.  问题: 那第一层的 删除和置顶等按钮不是被覆盖了吗?  对 要的就是这种效果,现在的解决思路就是在uiview 上添加一个 pa

iOS开发项目篇—40搭建cell的基本结构

iOS开发项目篇—40搭建cell的基本结构 一.简单说明 1.策略:针对微博可能出现的多种情况(只有文字,有文字有配图,有转发微博等),一次性加载所用的子控件到cell中,对于没有数据的空间进行隐藏.(不管cell以后会显示什么子控件,把所有有可能显示的子控件都添加上去·添加到contentView上) 微博cell的显示示例: 2.自定义cell的步骤: 1.新建一个继承自UITablecell的子类 2.在initWithStyle:方法中进行子控件的初始化 (1)将有可能显示的所有子控件

iOS开发——高级UI&带你玩转UITableView

带你玩装UITableView 在实际iOS开发中UITableView是使用最多,也是最重要的一个控件,如果你不会用它,那别说什么大神了,菜鸟都不如. 其实关于UItableView事非常简单的,实际开发中用起来却没有那么简单就是因为他结合MVC使用,涉及到了模型数据的读取,自定义View,功能的拓展和更好的解藕,下面就带你玩一遍: UITableView的两种样式 UITableViewStylePlain UITableViewStyleGroupeds accessoryType UIT

在iOS 7中使用storyboard(part 1)

原文:Storyboards Tutorial in iOS 7: Part 1 感谢翻译小组成员heartasice热心翻译.如果您有不错的原创或译文,欢迎提交给我们,更欢迎其他朋友加入我们的翻译小组(联系qq:2408167315). ========================================================================================== Storyboard是一项令人兴奋的功能,在iOS5中首次推出,在开发app的

发现,朋友圈样式开发总结

功能点: 评论,点赞功能,跟微信朋友圈一样的效果 优化点 Set model 方法,抽出几个view 封装 Artlist model 计算高度的方法,去掉不用的方法 数组处理的model 去掉不需要的方法userIco 主要优化控制器和大cell 直接在image carrier 里面写tableview ,不用单独写这个tableview 类 去掉did select 通知 黑色view 加动画 随机广告,加数组 评论回复两个接口 评论显示的昵称,不是电话号码 图片高度,适配问题 有什么收货

[iOS基础控件 - 6.6] 展示团购数据 自定义TableViewCell

A.需求 1.头部广告 2.自定义cell:含有图片.名称.购买数量.价格 3.使用xib设计自定义cell,自定义cell继承自UITableViewCell 4.尾部“加载更多按钮”,以及其被点击之后的数据加载刷新.动画效果 B.实现 1.使用MVC M:团购Model V:总View.cell的View(包含类和界面) C:ViewController 2.分类管理代码文件 3.尾部footerView “加载更多"功能 1 // 设置尾部控件 2 self.tableView.table

Cocoapods的使用教程

前言 对于iOS App的开发,几乎都采用了Cocoapods来管理第三方库,那么对于我们开发人员来说,这是必备技能,必须要掌握如何使用.这篇文章就是介绍如何安装和使用CocoaPods的. 这篇文章对哪些人群参考价值? 对未使用过Cocoapods的人群有参考价值 对使用过Cocoapods,但是未深入了解过的用户有参考价值 对有开源精神的,希望将自己的代码贡献到Cocoapods的用户有参考价值 如果您不属于以上人群,您是可以不阅读本篇文章的,当然阅读完也会有很大的帮助. 温馨提示:在篇文章

cern-cloud-architecture

规模: 总体: 有26个Cell 一个数据中心运行控制节点,另外一个仅仅运行nova cell 统一,灵活 nova-api运行在VM中,当然需要至少一个部署在物理机上来启动VM. 每个cell只有一个controller同时运行在VM中,如果用3个的话,随着cell的增多将很难维护. controller如果失败,则用另外VM的replace. 设计了cell capabilities filter来调度. 同时还设计了可以project来调度cell.社区实现了没? 巧用cell AGG 迁