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

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; i0) {
        for (int i=0; i

由于没有找到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

你可能感兴趣的:(UITableViewCell自适应高度完整示例)