UITableViewCell自适应高度完整示例

Cell的动态高度有很多种方法。在这里我主要记录一下自适应自iOS7开始支持的estimatedRowHeight自适应方法。


这里我以一个简陋的“朋友圈”为例子。会有一个动态高度的文本,和一个动态数量的九宫格图片。
用到的第三方框架是Masonry

1、初始化tableView

ViewController里,初始化我们的tableView,在这里tableViewViewController的属性变量。

_tableView = [UITableView new];
_tableView.delegate = self;
_tableView.dataSource = self;
_tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
_tableView.allowsSelection = NO;
[_tableView registerClass:[SmartTableViewCell class] forCellReuseIdentifier:kCellIdentifier];
[self.view addSubview:_tableView];
[_tableView mas_makeConstraints:^(MASConstraintMaker *make) {
    make.top.equalTo(self.view).with.offset(20);
    make.left.equalTo(self.view);
    make.bottom.equalTo(self.view);
    make.width.equalTo(self.view);
}];
_tableView.estimatedRowHeight = 60;

重要的是最后一句代码。estimatedRowHeight为预估行高,其实随便设置个值都成反正我们是自适应的,但是不能不设。
至于很多教程里说的_tableView.rowHeight = UITableViewAutomaticDimension;,其实我发现不写也没关系。查看API也可以发现UITableViewAutomaticDimension

// Returning this value from tableView:heightForHeaderInSection: or tableView:heightForFooterInSection: results in a height that fits the value returned from
// tableView:titleForHeaderInSection: or tableView:titleForFooterInSection: if the title is not nil.

tableView:heightForHeaderInSection或者tableView:heightForFooterInSection:的返回值是适应高度。是针对Header和Footer的,和Cell本身没啥关系。

2、初始化UItableViewCell

首先把控件摆出来。有一个名字,一个消息,一个九宫格。

- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
    if (self) {
        _nameLabel = [UILabel new];
        [_nameLabel setTextColor:[UIColor blueColor]];
        [self.contentView addSubview:_nameLabel];
        [_nameLabel mas_makeConstraints:^(MASConstraintMaker *make) {
            make.top.equalTo(self.contentView);
            make.left.equalTo(self.contentView);
            make.right.equalTo(self.contentView);
        }];
        
        _messageLabel = [[UILabel alloc]init];
        _messageLabel.numberOfLines = 0;
        [self.contentView addSubview:_messageLabel];
        [_messageLabel mas_makeConstraints:^(MASConstraintMaker *make){
            make.left.equalTo(self.contentView);
            make.right.equalTo(self.contentView);
            make.top.equalTo(_nameLabel.mas_bottom);
            make.bottom.equalTo(self.contentView).priorityLow();
        }];
        
        _imageViews = [NSMutableArray new];
        for (int i=0; i<kMaxImageCount; i++) {
            UIImageView *imageView = [UIImageView new];
            [self.contentView addSubview:imageView];
            [_imageViews addObject:imageView];
        }
    }
    return self;
}

Cell的高度需要自适应,方法是约束contentViewtopbottom
nameLabel中我指定make.top.equalTo(self.contentView);
messageLabel中我指定了make.bottom.equalTo(self.contentView).priorityLow();

这样一来,不管我的nameLabelmessageLabel有几排,甚至中间还有没有别的控件,反正Celltopbottom总是将nameLabelmessageLabel包含在内的。如此就实现了在没有九宫格时的高度自适应。

在这里我并没有九宫格的的约束,只是将控件摆了上去。因为在九宫格是动态的,我在初始化控件时并不知道Cellbottom应该与哪个Image相约束。

3、UITableViewCell的赋值

在这里需要注意的是,由于Cell的高度是自适应的,所以我们不能向寻常Cell赋值一样,将Model传入Cell后,在-(void)layoutSubviews;里进行赋值。应该在赋值时,直接把值给控件,然后让控件去自适应。
这里我自定义了一个简单的Model:

@interface Info : NSObject
@property(nonatomic, strong)NSString *name, *message;
@property(nonatomic, strong)NSMutableArray *images;
@end

@implementation Info
@end

赋值时:

- (void)setInfo:(Info *)info {
    _info = info;
    self.nameLabel.text = _info.name;
    self.messageLabel.text = _info.message;
    NSInteger count = [[_info images]count];
    for (int i=0; i<kMaxImageCount; i++) {
        [_imageViews[i] setHidden:YES];
        [_imageViews[i] mas_remakeConstraints:^(MASConstraintMaker *make){
            make.width.mas_equalTo(IMAGE_WIDTH);
            make.height.mas_equalTo(IMAGE_HEIGHT);
            make.centerX.equalTo(self.contentView).multipliedBy(((i%3)*2+1.0)/3);
            make.top.equalTo(_messageLabel.mas_bottom).offset(IMAGE_HEIGHT*(i/3));
        }];
    }
    if (count>0) {
        for (int i=0; i<count; i++) {
            [_imageViews[i] setImage:[_info images][i]];
            [_imageViews[i] setHidden:NO];
            if (i==count-1) {
                [_imageViews[i] mas_makeConstraints:^(MASConstraintMaker *make){
                    make.bottom.equalTo(self.contentView).priorityHigh();
                }];
            }
        }
    }
}

由于没有找到Masonry删除某条约束的方法,所以在这里每次赋值时,干脆重新还原了所有image的约束,这样可以确保Cell在复用的时候,不会受到影响。(这块可以优化)
接下来,遍历用户的图片并依次设置到九宫格,当遍历到最后一张图片,则设置当前UIImageViewbottom就是Cellbottom

注意一个细节,我设置了两遍Cellbottom,分别是messageLabel和九宫格的最后一个imageView

[_messageLabel mas_makeConstraints:^(MASConstraintMaker *make){
    make.left.equalTo(self.contentView);
    make.right.equalTo(self.contentView);
    make.top.equalTo(_nameLabel.mas_bottom);
    make.bottom.equalTo(self.contentView).priorityLow();
}];
[_imageViews[i] mas_makeConstraints:^(MASConstraintMaker *make){
    make.bottom.equalTo(self.contentView).priorityHigh();
}];

他们并不会相互冲突,Masonry默认的优先级为priorityMedium(),约束时会按照优先级优先进行约束。在没有图片时,只有messageLabelCellbottom进行了约束,于是Cellbottom就是messageLabelbottom;有图片时,最后一张图片也对Cellbottom进行了约束,且优先级更高,于是Cellbottom约束更改为最后一张图片的bottom

如此,全部完成。点击下载Demo

gif.gif
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,445评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,889评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,047评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,760评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,745评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,638评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,011评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,669评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,923评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,655评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,740评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,406评论 4 320
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,995评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,961评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,023评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,483评论 2 342

推荐阅读更多精彩内容