iOS开发入门iOS 控件定制ios实用开发技巧

自适应TableViewCell(纯代码)

2016-12-06  本文已影响783人  PencilCarefully

![Uploading 8FB0E81F-0248-4B0C-ABD0-32D057FD66AB_778307.png . . .]

前言:在iOS程序开发中,TableView的实用是最常见的,在一些比较特殊的需求下,必须展示的是用户评论信息,或发布的微博,这样的情况下,固定高度的cell显然是不能实现我们的需求,这就需要我们根据需要展示的内容,动态的设置cell的高度.下面是我做的一个Demo, 我们一起来做一下如何去实现这样的功能,希望能够对你起到一定的帮助.下面是效果图.

图1.gif

1 . 首先来我们分析一下这个需求,很显然这是一个可以滑动的列表,很自然我们就会想到用tableView去实现.在这个列表上面,每一个cell存放一条用户发送的数据,这些数据包括用户的名字,用户发送的正文内容,另外就是有一些是有配图的,有一些是没配图的.另外就是单元格的高度会随着内容的变化而变大或者变小.分析完这些,那我们开始撸代码,既然我们没有做过自适应高度的需求,那我们总做过高度固定的单元格吧,那就索性先给一个固定高度,然后再去调整. 接着我们去创建viewController.并且给tableView注册自定义单元格.

    self.tableView = [[UITableView alloc] initWithFrame:[UIScreen mainScreen].bounds style:UITableViewStylePlain];
    [self.tableView registerClass:[AdaptiveTableViewCell class] forCellReuseIdentifier:identifier];
    self.tableView.delegate = self;
    self.tableView.dataSource = self;
    [self.view addSubview:self.tableView];

2 . 创建model类,添加数据源,并且保存在数组中.这个数据源我是写在了,plist文件当中,并且使用cocoaPods导入MJExtension进行数据转模型.

#pragma mark - 懒加载
- (NSArray *)dataSource {
    if (!_dataSource) {
        self.dataSource = [AdaptiveModel mj_objectArrayWithFilename:@"ModelList.plist"];
    }
    return _dataSource;
}

3 . 在自定义的cell中添加重写初始化方法,添加子控件.

// 重写初始化方法
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
    if (self) {
        [self setupView];
    }
    return self;
}

// 添加子控件
- (void)setupView {
    UILabel *nameLabel = [UILabel new];
    [self.contentView addSubview:nameLabel];
    nameLabel.textColor = [UIColor orangeColor];
    nameLabel.font = [UIFont systemFontOfSize:17];
    self.nameLabel = nameLabel;
    
    UILabel *textLabel = [[UILabel alloc] init];
    textLabel.numberOfLines = 0;
    textLabel.font = [UIFont systemFontOfSize:14];
    [self.contentView addSubview:textLabel];
    self.text_Label = textLabel;
    
    UIImageView *pictureView = [[UIImageView alloc] init];
    [self.contentView addSubview:pictureView];
    self.picthreView = pictureView;
}

4 . 注意在添加子控件的时候我是没有给出控件的frame的.因为单元格的高度要根据需要展示的内容来动态计算的,那我们就在model类里面动态的计算出控件的framecell的高度,并且保存在model类中. 注意在model中要把#import <Foundation/Foundation.h>框架更改成#import <UIKit/UIKit.h>否则没法添加CGRect属性.

#import <UIKit/UIKit.h>
// 模型
@interface AdaptiveModel : NSObject

@property (nonatomic, copy) NSString *name;         // 昵称
@property (nonatomic, copy) NSString *text;         // 正文
@property (nonatomic, copy) NSString *picture;      // 图片

@property (nonatomic, assign) CGRect nameFrame;     // 昵称的frame
@property (nonatomic, assign) CGRect textFrame;     // 正文的frame
@property (nonatomic, assign) CGRect pictureFrame;  // 图片的frame
@property (nonatomic, assign) CGFloat cellHeight;    // 单元格高度

@end

5 .然后再model.m中懒加载计算出各个控件的framecell的高度

#import "AdaptiveModel.h"
#define Space 10          // 间距
@implementation AdaptiveModel

// 懒加载
- (CGFloat)cellHeight {
    if (_cellHeight == 0) {
        CGFloat nameX = Space;
        CGFloat namey = Space;
        
        // 获取文字宽度
        //    CGSize nameSzie = [self getLabalSizeWithLabel:self.nameLabel];
        NSDictionary *attribute = @{NSFontAttributeName : [UIFont systemFontOfSize:17]};
        CGSize nameSize = [self.name sizeWithAttributes:attribute];
        self.nameFrame = CGRectMake(nameX, namey, nameSize.width, nameSize.height);
        // 正文
        CGFloat textW = [UIScreen mainScreen].bounds.size.width - Space * 2;
        NSDictionary *attribute1 = @{NSFontAttributeName: [UIFont systemFontOfSize:14]};
        CGSize textsize =  [self.text boundingRectWithSize:CGSizeMake(textW, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin attributes:attribute1 context:nil].size;
        //    CGFloat textH = [self getLabelSizeWithLabel:self.text_Label width:textW];
        self.textFrame = CGRectMake(Space, CGRectGetMaxY(self.nameFrame) + Space, textW, textsize.height);
        // 图片
        if (self.picture) {
            self.pictureFrame = CGRectMake(Space, CGRectGetMaxY(self.textFrame) + Space, 100, 100);
            _cellHeight = CGRectGetMaxY(self.pictureFrame) + Space;
        } else {
            _cellHeight = CGRectGetMaxY(self.textFrame) + Space;
        }
    }
    return _cellHeight;
}

@end

注意事项:
注意在此时用到了2个方法,第一个是获取文字尺寸,这个方法仅限于label没有换行,需要获取文字宽度时使用.需要注意的地方就是设置的font和你label控件设置的font必须是一致的.

  // 获取文字宽度
        NSDictionary *attribute = @{NSFontAttributeName : [UIFont systemFontOfSize:17]};
        CGSize nameSize = [self.name sizeWithAttributes:attribute];

第二个方法也是获取文字尺寸,和第一个方法不同的是这个是可以换行的,需要注意的是不仅要设置font和你设置的labelfont必须是一致的,还要给它设置一个最大的宽度,告诉它最大宽度时多少,才会自动换行.

  // 正文
        CGFloat textW = [UIScreen mainScreen].bounds.size.width - Space * 2;
        NSDictionary *attribute1 = @{NSFontAttributeName: [UIFont systemFontOfSize:14]};
        CGSize textsize =  [self.text boundingRectWithSize:CGSizeMake(textW, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin attributes:attribute1 context:nil].size;

6 .接下来我们计算好了cell的高度,就在tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath这个方法中设置cell的高度就可以了.

// 设置单元格高度
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    
    AdaptiveModel *model = self.dataSource[indexPath.row];
    return model.cellHeight;
}

7 . 设置单元格,给单元格上的控件赋值

// 设置单元格
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    AdaptiveTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier forIndexPath:indexPath];
    // 传递数组模型
    cell.model = self.dataSource[indexPath.row];
    return cell;
}

8 .在自定义的cell里面重写属性的setter方法,给子控件赋值,并且设置控件的frame

// 重写属性的setter方法
- (void)setModel:(AdaptiveModel *)model {
    if (_model != model) {
        _model = model;
    }
    self.nameLabel.text = model.name;
    self.text_Label.text = model.text;
    if (model.picture) { // 有图片
        self.picthreView.hidden = NO;
        self.picthreView.image = [UIImage imageNamed:model.picture];
    } else {            // 没有图片
        self.picthreView.hidden = YES;
    }
    // 设置控件的frame
    self.nameLabel.frame = self.model.nameFrame;
    self.text_Label.frame = self.model.textFrame;
    self.picthreView.frame = self.model.pictureFrame;
}

总结:以上就是自适应TableViewCell的全过程,我们可以得出以下的结论,要想去实现tableView自适应高度,首先我们需要计算出model中各个控件的frame和所需要的cell的高度.然后再设置单元格高度的方法中,设置单元格所需要的高度.最后再把各个控件的frame传递到cell中来设置.

当然还有其他的实现方法, 我这里只是给出了一个思路,具体怎么实现,还需要你自己去动脑子思考,希望能够对你起到一定的帮助作用.

另附gitHub下载地址

下一篇:自适应TableViewCell(XIB)

上一篇 下一篇

猜你喜欢

热点阅读