如何使用Masonry设计复合型cell

原文地址:如何使用Masonry设计复合型cell

前言

其实早在@sunnyxx同学发布UIView-FDCollapsibleConstraints的时候 我就说要写一下怎么用代码来稍微麻烦的实现复用的问题 但是一直各种没时间(主要是我的办法太复杂 - -) 正好看到@叶孤城同学也说了一下他的解决办法 所以我来说一下我是如何解决这个问题的

分析

我们以叶孤城同学的例子来简单分析一下 假设view是这样的(为了方便 将所有的间隙设定为20)
正常的布局是这样的

布局代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65

@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又缩短间隙的目的

代码较长 大家可以选择跳过 - -!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127

@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是否被显示)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
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中我们只要这样做就可以了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
- (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的方式 面对同时在横向和纵向都有隐藏要求的时候 会方便很多
比如文中举的例子 第一行有时会隐藏蓝色的按钮 有时整个一行都会不显示 这样的话 当我想隐藏按钮时 只要激活按钮的约束 想隐藏整行时 只要激活整行的那条约束就行了

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Go语言(也称为Golang)是由Google开发的一种静态强类型、编译型的编程语言。它旨在成为一门简单、高效、安全和并发的编程语言,特别适用于构建高性能的服务器和分布式系统。以下是Go语言的一些主要特点和优势: 简洁性:Go语言的语法简单直观,易于学习和使用。它避免了复杂的语法特性,如继承、重载等,转而采用组合和接口来实现代码的复用和扩展。 高性能:Go语言具有出色的性能,可以媲美C和C++。它使用静态类型系统和编译型语言的优势,能够生成高效的机器码。 并发性:Go语言内置了对并发的支持,通过轻量级的goroutine和channel机制,可以轻松实现并发编程。这使得Go语言在构建高性能的服务器和分布式系统时具有天然的优势。 安全性:Go语言具有强大的类型系统和内存管理机制,能够减少运行时错误和内存泄漏等问题。它还支持编译时检查,可以在编译阶段就发现潜在的问题。 标准库:Go语言的标准库非常丰富,包含了大量的实用功能和工具,如网络编程、文件操作、加密解密等。这使得开发者可以更加专注于业务逻辑的实现,而无需花费太多时间在底层功能的实现上。 跨平台:Go语言支持多种操作系统和平台,包括Windows、Linux、macOS等。它使用统一的构建系统(如Go Modules),可以轻松地跨平台编译和运行代码。 开源和社区支持:Go语言是开源的,具有庞大的社区支持和丰富的资源。开发者可以通过社区获取帮助、分享经验和学习资料。 总之,Go语言是一种简单、高效、安全、并发的编程语言,特别适用于构建高性能的服务器和分布式系统。如果你正在寻找一种易于学习和使用的编程语言,并且需要处理大量的并发请求和数据,那么Go语言可能是一个不错的选择。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值