如何使用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/

欢迎加群互相学习,共同进步。QQ群:iOS: 58099570 | Android: 330987132 | Go:217696290 | Python:336880185 | 做人要厚道,转载请注明出处!http://www.cnblogs.com/sunshine-anycall/p/4812790.html

时间: 2024-08-04 01:57:33

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

Tumblr 架构设计

最近的新闻中我们得知雅虎11亿美元收购了Tumblr: Yahoo bought Tumblr for $1.1 billion. 你也许会发现Instagram也被Facebook重金收购的介绍. 这是一个巧合吗?这就由你来判断吧 为什么雅虎会收购Tumblr? 这场交易中的商业价值我可能无法判断,但是如果你对Tumblr的技术方面有所了解,你一定会为Tumblr竖起大拇指. 为什么这么说呢,请接着读... Tumblr每月页面浏览量超过150亿次,已经成为火爆的博客社区.用户也许喜欢它的简约

对话英特尔中研院宋继强:英特尔 AI 加持春哥最新 MV 的背后

如果没有2005年的爆红,这些数以万计的陌生人或许就不会站在雨里,为台上的偶像李宇春"打 call",而李宇春也不会在走红12年后,为台下的这些人创作一首给他们的歌--<今天雨,可是我们在一起>. 2005年,除了李宇春夺冠,其实还有两件事在被庆祝着:一件是英特尔正在庆祝自己入华20周年,还专门成立了一支投资基金,规划了一系列投资计划:另一件是中国计算机界正在筹备人工智能诞生50周年的纪念活动,彼时的人工智能还坐在冷板凳上. 12年后,这几条线有了一个交点:李宇春为自己的粉

iOS开发一款小巧简洁的日历控件

iOS开发一款小巧简洁的日历控件 一.引言         日 历是iOS开发中有时会用到的一个UI控件,网上开源的代码也很多,我浏览过一些,大致有两种模式,一种是日历的逻辑由开发者自己实现,通过计算闰年与平 年来确定月份天数,另外一种模式是通过NSDate这个时间类,来获取日历的信息.我个人认为后一种更加安全,代码性能也会更加优质,下面就是我用这种模 式实现的一个日历控件. 二.设计思路 1.先来看下效果吧                     2.我们需要实现的功能 (1)每行7天,对应星

Tumblr:150亿月浏览量背后的架构挑战

Tumblr:150亿月浏览量背后的架构挑战 2013/04/08 · IT技术, 开发 · 9.9K 阅读 · HBase, Tumblr, 架构 英文原文:High Scalability,编译:CSDN 导读:和许多新兴的网站一样,著名的轻博客服务Tumblr在急速发展中面临了系统架构的瓶颈.每天5亿次浏览量,峰值每秒4万次请求,每天3TB新的数据存储,超过1000台服务器,这样的情况下如何保证老系统平稳运行,平稳过渡到新的系统,Tumblr正面临巨大的挑战.近日,HighScalabil

用状态机来设计cell动画

用状态机来设计cell动画   前言 一个cell可能有好几种状态,比方说选中状态与未选中状态,以及失效状态等等状态,我们将这些不同的情形抽象成一个个状态机,用状态机切换逻辑来设计复杂的动画效果,达到简化设计的目的,大大增加程序可维护性. * 大家需要注意一点,cell因为是可以复用的控件,因为存在复用,所以里面存在较为恶心的复用逻辑,设计动画接口时是需要注意这些小细节的.(亲手写过的人一定会深有体会)   效果   源码 https://github.com/YouXianMing/CellS

基于Masonry自动计算cell的高度

/** * This is a very very helpful category for NSTimer. * * @author huangyibiao * @email huangyibiao520@163.com * @github https://github.com/632840804 * @blog http://blog.csdn.net/woaifen3344 * * @note Make friends with me. * Facebook: huangyibiao520

Cell组件设计报表是不是控件拖上去就是个最简单的组件了?

问题描述 小弟比较菜,请问用CELL开发报表组件,是不是直接就是1个类似DLL的组件了,还是程序写完以后还要进行其他工作才能变成1个组件 解决方案 解决方案二:该回复于2009-06-18 17:16:52被版主删除解决方案三:一般情况下是吧--你建了一个工程之后,直接去点击中build键,你就有了一个DLL--是一个什么都不会干的DLL--解决方案四:该回复于2009-05-18 10:06:07被版主删除

利用Visual Basic设计打印复杂报表

一.用VB创建外部EXCEL对象 大多数大型ActiveX-enabled应用程序和其它ActiveX部件,在它们的对象层次中都提供了一个顶层外部可创建对象.该对象提供了对该层次中其它对象的访问,并且还提供对整个应用程序起作用的方法和属性. 例如,每个MicrosoftOffice应用程序提供一个顶层Application对象.下面语句显示了对Microsoftoffice/9.shtml'target='_blank'class='article'>Excel的Application对象的引用

解决tableView中cell动态加载控件的重用问题

解决tableView中cell动态加载控件的重用问题 tableView的cell,有时候需要在运行时取得对应的数据后才能够动态的创建该cell中的控件并加载到该cell中,此时,你一定会遇到重用问题,即使你能做到该cell只根据数值加载了一回控件,你也没法保证不出现重用问题:) 效果(请注意查看,移动下面的格子时,上面出现了重用的问题) 源码: YXCell.h // // YXCell.h // YXTableView // // Copyright (c) 2014年 Y.X. All