前两天做了一个项目,中间有遇到一个问题,就是聊天的时候cell高度的问题。这是一个很多前辈都遇到过,并且很完美的解决过的问题。这里主要是记录自己的学习心得。项目中首先想到的是用三方库,可是有问题,遂放弃,自己写一个,但是没有封装。项目地址
UITableView 的属性特征什么的,这里就暂时不做介绍了。
由于聊天内容比较简单,不需要对聊天做出很多操作,只是简单的使用 UILable 进行展示即可。首先我们定义一个模型 JXChatModel
// // JXChatModel.h // JXAutoCell // // Created by 王加祥 on 16/9/28. // Copyright © 2016年 王加祥. All rights reserved. // #import <UIKit/UIKit.h> @interface JXChatModel : NSObject // 字典模型转换 + (instancetype)modelWithDict:(NSDictionary *)dict; /** 昵称 */ @property (nonatomic,copy) NSString * nickName; /** 等级 */ @property (nonatomic,copy) NSString * graide; /** 内容 */ @property (nonatomic,copy) NSString * content; /** 高度,用来存放计算后的cell高度 */ @property (nonatomic,assign) CGFloat cellHeight; @end
// // JXChatModel.m // JXAutoCell // // Created by 王加祥 on 16/9/28. // Copyright © 2016年 王加祥. All rights reserved. // #import "JXChatModel.h" @implementation JXChatModel + (instancetype)modelWithDict:(NSDictionary *)dict { JXChatModel * model = [[self alloc] init]; [model setValuesForKeysWithDictionary:dict]; return model; } - (void)setValue:(id)value forUndefinedKey:(NSString *)key { // 这里对没有定义的键值对不进行任何操作 } @end
- 自定义 UITableViewCell
前面我们定义了一个数据模型,当我们请求过来的数据之后,我们首先将数据转换成模型,之后直接将模型赋值给我们自定义的表格,这样做有极大的好处
// // JXChatCell.h // JXAutoCell // // Created by 王加祥 on 16/9/28. // Copyright © 2016年 王加祥. All rights reserved. // #import <UIKit/UIKit.h> @class JXChatModel; @interface JXChatCell : UITableViewCell /** 模型 */ @property (nonatomic,strong) JXChatModel * model; @end
// // JXChatCell.m // JXAutoCell // // Created by 王加祥 on 16/9/28. // Copyright © 2016年 王加祥. All rights reserved. // #import "JXChatCell.h" #import "JXChatModel.h" #import "Masonry.h" /** 等级图片宽度 */ #define kIconWidth 25 /** 等级图片高度 */ #define kIconHeight 25 #define kWidth [UIScreen mainScreen].bounds.size.width @interface JXChatCell () /** 头像 */ @property (nonatomic,weak) UIImageView * iconImageView; /** 昵称 */ @property (nonatomic,weak) UILabel * nickNameLabel; /** 内容 */ @property (nonatomic,weak) UILabel * contentLabel; @end @implementation JXChatCell - (void)setModel:(JXChatModel *)model { NSString * name = [NSString stringWithFormat:@"rank_%@",model.graide]; self.iconImageView.image = [UIImage imageNamed:name]; self.nickNameLabel.text = model.nickName; [self.nickNameLabel sizeToFit]; CGRect frame = self.nickNameLabel.frame; frame.size.height = kIconHeight; self.nickNameLabel.frame = frame; // 设置内容宽度,这里首先在自适应之前需要将内容的宽度固定 self.contentLabel.text = model.content; CGRect contentFrame = self.nickNameLabel.frame; contentFrame.size.width = kWidth - kIconWidth - self.nickNameLabel.frame.size.width - 80; self.contentLabel.frame = contentFrame; [self.contentLabel sizeToFit]; model.cellHeight = CGRectGetMaxY(self.contentLabel.frame) + 10; } #pragma mark - 布局 - (void)layoutSubviews { [super layoutSubviews]; // 等级图片 self.iconImageView.frame = CGRectMake(5, 0, kIconWidth, kIconHeight); // 昵称 self.nickNameLabel.frame = CGRectMake(kIconWidth + 10 , 0, self.nickNameLabel.frame.size.width, kIconHeight); // 内容大小 self.contentLabel.frame = CGRectMake(CGRectGetMaxX(self.nickNameLabel.frame) + 5, 5, self.contentLabel.frame.size.width, self.contentLabel.frame.size.height); } #pragma mark - 懒加载 - (UIImageView *)iconImageView{ if (_iconImageView == nil) { UIImageView * iconImageView = [[UIImageView alloc] init]; [self.contentView addSubview:iconImageView]; _iconImageView = iconImageView; } return _iconImageView; } - (UILabel *)nickNameLabel{ if (_nickNameLabel == nil) { UILabel * nickNameLabel = [[UILabel alloc] init]; nickNameLabel.textColor = [UIColor orangeColor]; nickNameLabel.font = [UIFont systemFontOfSize:13.0]; [self.contentView addSubview:nickNameLabel]; _nickNameLabel = nickNameLabel; } return _nickNameLabel; } - (UILabel *)contentLabel{ if (_contentLabel == nil) { UILabel * contentLabel = [[UILabel alloc] init]; contentLabel.textColor = [UIColor blackColor]; contentLabel.numberOfLines = 0; contentLabel.font = [UIFont systemFontOfSize:13.0]; [self.contentView addSubview:contentLabel]; _contentLabel = contentLabel; } return _contentLabel; } @end
- 控制器部分代码
在控制器中我们需要操作的就稍微少了点了,这里我们只需要将数据请求下来,然后将数据转换成模型,存到数组中。之后的 UITableView 数据源就根据这个数组来操作
// // ViewController.m // JXAutoCell // // Created by 王加祥 on 16/9/28. // Copyright © 2016年 王加祥. All rights reserved. // 自动计算行高 #import "ViewController.h" #import "JXChatCell.h" #import "JXChatModel.h" @interface ViewController ()<UITableViewDelegate,UITableViewDataSource> /** 数据源数组 */ @property (nonatomic,strong) NSMutableArray * chatArray; /** UITableView */ @property (nonatomic,weak) UITableView * tableView; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // 数据 NSArray * array = @[ @{ @"nickName":@"你成佛了", @"graide":@"16", @"content":@"连接方式李金发欧式24234242342冯绍峰烦死拉伸的减肥了敬爱是骄傲是激发按时发放费;啊; 拉伸放假接方式李反对党的圾费垃圾房间爱乱收费;啊; 拉伸放假啊;发;是放假啊;了解算法lkjslajflsajflasjlasjflajflj零距离圣诞节佛按实际大量积分垃圾地方啦垃圾了房间爱令肌肤拉伸件地方垃圾垃圾了极大浪费就暗恋的激发了设计费垃圾费拉激发偶尔加乱收费来释放接方式李反对党的圾费垃圾房间爱乱收费;啊; 拉伸放假啊;发;是放假啊;了解算法lkjslajflsajflasjlasjflajflj零距离圣诞节佛按实际大量积分垃圾地方啦垃圾了房间爱令肌肤拉伸件地方垃圾垃圾了极大浪费就暗恋的激发了设计费垃圾费拉激发偶尔加乱收费来释放接方式李反对党的圾费垃圾房间爱乱收费;啊; 拉伸放假啊;发;是放假啊;了解算法lkjslajflsajflasjlasjflajflj零距离圣诞节佛按实际大量积分垃圾地方啦垃圾了房间爱令肌肤拉伸件地方垃圾垃圾了极大浪费就暗恋的激发了设计费垃圾费拉激发偶尔加乱收费来释放接方式李反对党的圾费垃圾房间爱乱收费;啊; 拉伸放假啊;发;是放假啊;了解算法lkjslajflsajflasjlasjflajflj零距离圣诞节佛按实际大量积分垃圾地方啦垃圾了房间爱令肌肤拉伸件地方垃圾垃圾了极大浪费就暗恋的激发了设计费垃圾费拉激发偶尔加乱收费来释放啊;发;是放假啊;了解算法来释放" }, @{ @"nickName":@"式李金发", @"graide":@"13", @"content":@"连接方式323242342432圾房间爱乱收费;啊; 拉伸放假啊;发;是放假啊;了解算法来释放" }, @{ @"nickName":@"垃圾费垃圾房间", @"graide":@"1", @"content":@"连接方式李反对党的圾费垃圾房间爱乱收费;啊; 拉伸放假啊;发;是放假啊;了解算法来释放" }, @{ @"nickName":@"了仨解放啦", @"graide":@"6", @"content":@"连接方式沙发沙发" }, @{ @"nickName":@"式李金发", @"graide":@"13", @"content":@"连接方式323242342432圾房间爱乱收费;啊; 拉伸放假啊;发;是放假啊;了解算法来释放" }, @{ @"nickName":@"垃圾费垃圾房间", @"graide":@"1", @"content":@"连接方式李反对党的圾费垃圾房间爱乱收费;啊; 拉伸放假啊;发;是放假啊;了解算法来释放" }, @{ @"nickName":@"式李金发", @"graide":@"13", @"content":@"连接方式323242342432圾房间爱乱收费;啊; 拉伸放假啊;发;是放假啊;了解算法来释放" }, @{ @"nickName":@"垃圾费垃圾房间", @"graide":@"1", @"content":@"连接方式李反对党的圾费垃圾房间爱乱收费;啊; 拉伸放假啊;发;是放假啊;了解算法来释放" }, @{ @"nickName":@"式李金发", @"graide":@"13", @"content":@"连接方式323242342432圾房间爱乱收费;啊; 拉伸放假啊;发;是放假啊;了解算法来释放" }, @{ @"nickName":@"垃圾费垃圾房间", @"graide":@"1", @"content":@"连接方式李反对党的圾费垃圾房间爱乱收费;啊; 拉伸放假啊;发;是放假啊;了解算法来释放" }, @{ @"nickName":@"式李金发", @"graide":@"13", @"content":@"连接方式323242342432圾房间爱乱收费;啊; 拉伸放假啊;发;是放假啊;了解算法来释放" }, @{ @"nickName":@"垃圾费垃圾房间", @"graide":@"1", @"content":@"连接方式李反对党的圾费垃圾房间爱乱收费;啊; 拉伸放假啊;发;是放假啊;了解算法来释放" }, @{ @"nickName":@"式李金发", @"graide":@"13", @"content":@"连接方式323242342432圾房间爱乱收费;啊; 拉伸放假啊;发;是放假啊;了解算法来释放" }, @{ @"nickName":@"垃圾费垃圾房间", @"graide":@"1", @"content":@"连接方式李反对党的圾费垃圾房间爱乱收费;啊; 拉伸放假啊;发;是放假啊;了解算法来释放" }, @{ @"nickName":@"式李金发", @"graide":@"13", @"content":@"连接方式323242342432圾房间爱乱收费;啊; 拉伸放假啊;发;是放假啊;了解算法来释放" }, @{ @"nickName":@"垃圾费垃圾房间", @"graide":@"1", @"content":@"连接方式李反对党的圾费垃圾房间爱乱收费;啊; 拉伸放假啊;发;是放假啊;了解算法来释放" }, @{ @"nickName":@"式李金发", @"graide":@"13", @"content":@"连接方式323242342432圾房间爱乱收费;啊; 拉伸放假啊;发;是放假啊;了解算法来释放" }, @{ @"nickName":@"垃圾费垃圾房间", @"graide":@"1", @"content":@"连接方式李反对党的圾费垃圾房间爱乱收费;啊; 拉伸放假啊;发;是放假啊;了解算法来释放" }, @{ @"nickName":@"式李金发", @"graide":@"13", @"content":@"连接方式323242342432圾房间爱乱收费;啊; 拉伸放假啊;发;是放假啊;了解算法来释放" }, @{ @"nickName":@"垃圾费垃圾房间", @"graide":@"1", @"content":@"连接方式李反对党的圾费垃圾房间爱乱收费;啊; 拉伸放假啊;发;是放假啊;了解算法来释放" }, @{ @"nickName":@"式李金发", @"graide":@"13", @"content":@"连接方式323242342432圾房间爱乱收费;啊; 拉伸放假啊;发;是放假啊;了解算法来释放" }, @{ @"nickName":@"垃圾费垃圾房间", @"graide":@"1", @"content":@"连接方式李反对党的圾费垃圾房间爱乱收费;啊; 拉伸放假啊;发;是放假啊;了解算法来释放" }, @{ @"nickName":@"式李金发", @"graide":@"13", @"content":@"连接方式323242342432圾房间爱乱收费;啊; 拉伸放假啊;发;是放假啊;了解算法来释放" }, @{ @"nickName":@"垃圾费垃圾房间", @"graide":@"1", @"content":@"连接方式接方式李反对党的圾费垃圾房间爱乱收费;啊; 拉伸放假啊;发;是放假啊;了解算法lkjslajflsajflasjlasjflajflj零距离圣诞节佛按实际大量积分垃圾地方啦垃圾了房间爱令肌肤拉伸件地方垃圾垃圾了极大浪费就暗恋的激发了设计费垃圾费拉激发偶尔加乱收费来释放接方式李反对党的圾费垃圾房间爱乱收费;啊; 拉伸放假啊;发;是放假啊;了解算法lkjslajflsajflasjlasjflajflj零距离圣诞节佛按实际大量积分垃圾地方啦垃圾了房间爱令肌肤拉伸件地方垃圾垃圾了极大浪费就暗恋的激发了设计费垃圾费拉激发偶尔加乱收费来释放接方式李反对党的圾费垃圾房间爱乱收费;啊; 拉伸放假啊;发;是放假啊;了解算法lkjslajflsajflasjlasjflajflj零距离圣诞节佛按实际大量积分垃圾地方啦垃圾了房间爱令肌肤拉伸件地方垃圾垃圾了极大浪费就暗恋的激发了设计费垃圾费拉激发偶尔加乱收费来释放李反对党的圾费垃圾房间爱乱收费;啊; 拉伸放假啊;发;是放假啊;了解算法来释放" }, @{ @"nickName":@"式李金发", @"graide":@"13", @"content":@"连接方式接方式李反对党的圾费垃圾房间爱乱收费;啊; 拉伸放假啊;发;是放假啊;了解算法lkjslajflsajflasjlasjflajflj零距离圣诞节佛按实际大量积分垃圾地方啦垃圾了房间爱令肌肤拉伸件地方垃圾垃圾了极大浪费就暗恋的激发了设计费垃圾费拉激发偶尔加乱收费来释放323242342432圾房间爱乱收费;啊; 拉伸放假啊;发;是放假啊;了解算法来释放" }, @{ @"nickName":@"垃圾费垃圾房间", @"graide":@"1", @"content":@"连接方式接方式李反对党的圾费垃圾房间爱乱收费;啊; 拉伸放假啊;发;是放假啊;了解算法lkjslajflsajflasjlasjflajflj零距离圣诞节佛按实际大量积分垃圾地方啦垃圾了房间爱令肌肤拉伸件地方垃圾垃圾了极大浪费就暗恋的激发了设计费垃圾费拉激发偶尔加乱收费来释放李反对党的圾费垃圾房间爱乱收费;啊; 拉伸放假啊;发;是放假啊;了解算法来释放" }, @{ @"nickName":@"式李金发", @"graide":@"13", @"content":@"连接方式接方式李反对党的圾费垃圾房间爱乱收费;啊; 拉伸放假啊;发;是放假啊;了解算法lkjslajflsajflasjlasjflajflj零距离圣诞节佛按实际大量积分垃圾地方啦垃圾了房间爱令肌肤拉伸件地方垃圾垃圾了极大浪费就暗恋的激发了设计费垃圾费拉激发偶尔加乱收费来释放323242342432圾房间爱乱收费;啊; 拉伸放假啊;发;是放假啊;了解算法来释放" }, @{ @"nickName":@"垃圾费垃圾房间", @"graide":@"1", @"content":@"连接方式接方式李反对党的圾费垃圾房间爱乱收费;啊; 拉伸放假啊;发;是放假啊;了解算法lkjslajflsajflasjlasjflajflj零距离圣诞节佛按实际大量积分垃圾地方啦垃圾了房间爱令肌肤拉伸件地方垃圾垃圾了极大浪费就暗恋的激发了设计费垃圾费拉激发偶尔加乱收费来释放李反对党的圾费垃圾房间爱乱收费;啊; 拉伸放假啊;发;是放假啊;了解算法来释放" }, @{ @"nickName":@"式李金发", @"graide":@"13", @"content":@"连接方式接方式李反对党的圾费垃圾房间爱乱收费;啊; 拉伸放假啊;发;是放假啊;了解算法lkjslajflsajflasjlasjflajflj零距离圣诞节佛按实际大量积分垃圾地方啦垃圾了房间爱令肌肤拉伸件地方垃圾垃圾了极大浪费就暗恋的激发了设计费垃圾费拉激发偶尔加乱收费来释放323242342432圾房间爱乱收费;啊; 拉伸放假啊;发;是放假啊;了解算法来释放" }, @{ @"nickName":@"垃圾费垃圾房间", @"graide":@"1", @"content":@"连接方式李反对党的圾费垃圾房间爱乱收费;啊; 拉伸放假啊;发;是放假啊;了解算法lkjslajflsajflasjlasjflajflj零距离圣诞节佛按实际大量积分垃圾地方啦垃圾了房间爱令肌肤拉伸件地方垃圾垃圾了极大浪费就暗恋的激发了设计费垃圾费拉激发偶尔加乱收费来释放" } ]; // 将数据转换成模型 for (NSDictionary * dict in array) { JXChatModel * model = [JXChatModel modelWithDict:dict]; [self.chatArray addObject:model]; } [self.tableView reloadData]; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return self.chatArray.count; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString * identifier = @"cell"; JXChatCell * cell = [tableView dequeueReusableCellWithIdentifier:identifier]; if (cell == nil) { cell = [[JXChatCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier]; } cell.model = self.chatArray[indexPath.row]; return cell; } - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { JXChatModel * model = self.chatArray[indexPath.row]; return model.cellHeight; } // 先给cell表格一个预估计高度 - (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath { return 100; } - (NSMutableArray *)chatArray{ if (_chatArray == nil) { _chatArray = [NSMutableArray array]; } return _chatArray; } - (UITableView *)tableView{ if (_tableView == nil) { UITableView * tableView = [[UITableView alloc] init]; tableView.frame = self.view.bounds; tableView.delegate = self; tableView.dataSource = self; [self.view addSubview:tableView]; _tableView = tableView; } return _tableView; } @end
构建运行,展示效果
时间: 2024-10-05 23:52:19