最近在UItableViewCell的缓冲机制,相信很多开发者都已经清楚,假设手机屏幕一屏有6个cell,当再向上滑动的时候还会再创建一个,当第一个完全消失的时候,这时候再向上滑动的时候就会从缓冲池中找到类型相同的cell。这样就不用重复创建cell了。估计也有不少人遇到过当每个cell所要展示的内容不相同时,被复用折磨的困扰---遮盖原内容。下面我就介绍我的做法
- (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
WDSChatTableViewCell *cell = nil;
// 先获取消息模型
EMMessage *message = self.dataSources [indexPath.row];
if ([message.from isEqualToString:self.buddy.username]) {
// 接收方
cell = [tableView dequeueReusableCellWithIdentifier:ReceiveCell];
if (cell==nil)
{
cell = [[[NSBundle mainBundle]loadNibNamed:@"WDSChatTableViewCell" owner:self options:nil]lastObject];
}
}else{
// 发送
cell = [tableView dequeueReusableCellWithIdentifier:SendCell];
if (cell==nil)
{
cell = [[[NSBundle mainBundle]loadNibNamed:@"WDSChatTableViewCell" owner:self options:nil]lastObject];
}
}
// cell.messaLabel.text = self.dataSources[indexPath.row];
// 显示内容
/**
from wo to ta
*/
cell.message = message;
return cell;
}
先声明一下我写的demo是模仿环信的
#import "WDSChatTableViewCell.h"
#import "EMCDDeviceManager.h"
#import "WDSAudioPlayTool.h"
@interface WDSChatTableViewCell()
@property (nonatomic, strong)UIImageView *chatImageView;
@end
@implementation WDSChatTableViewCell
-(UIImageView *)chatImageView
{
if (!_chatImageView) {
_chatImageView = [[UIImageView alloc]init];
}
return _chatImageView;
}
- (void)awakeFromNib
{
// 此方法可以做初始化
//1.给label 添加敲击手势
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(messageLabTap:)];
[self.messaLabel addGestureRecognizer:tap];
}
#pragma mark--声音点击的时候触发的方法
- (void)messageLabTap:(UITapGestureRecognizer *)tap
{
// 只有当前的类型为语音的时候才需要播放
// 获取语音的消息体
id body = self.message.messageBodies[0];
if ([body isKindOfClass:[EMVoiceMessageBody class]]) {
NSLog(@"播放语音");
BOOL receiver = [self.reuseIdentifier isEqualToString:ReceiveCell];
[WDSAudioPlayTool playWithMessage:self.message magLabel:self.messaLabel receiver:receiver];
}
}
- (void)setMessage:(EMMessage *)message
{
[self.chatImageView removeFromSuperview];
// 关键点就在此处,懒加载imageView然后在重用的时候将
//UIImageView从父视图移除,这样就不会被复用遮盖了
_message = message;
id body = message.messageBodies[0];
if ([body isKindOfClass:[EMTextMessageBody class]]) {
EMTextMessageBody *textBody = body;
self.messaLabel.text = textBody.text;
}else if([body isKindOfClass:[EMVoiceMessageBody class]]){
self.messaLabel.attributedText = [self voiceAtt];
}else if ([body isKindOfClass:[EMImageMessageBody class]]){
[self showImage];
}else{
self.messaLabel.text = @"未知的类型";
}
}
#pragma mark--显示图片
- (void)showImage
{
if ([self.reuseIdentifier isEqualToString:SendCell]) {
// 获取图片消息体
EMImageMessageBody *imgBody = self.message.messageBodies[0];
CGRect thumbnailFrm = (CGRect){0,0,imgBody.thumbnailSize};
NSLog(@"%f",thumbnailFrm.size.height);
// 设置Label的尺寸足够显示UIimageView
NSTextAttachment *imgAttach = [[NSTextAttachment alloc]init];
imgAttach.bounds =thumbnailFrm;
// 占位思想
NSAttributedString *imgAtt = [NSAttributedString attributedStringWithAttachment:imgAttach];
self.messaLabel.attributedText = imgAtt;
//1.首先要在cell里面添加一个UIImageView
[self.messaLabel addSubview:self.chatImageView];
// 2.设置图片控件为缩略图的尺寸
self.chatImageView.frame = thumbnailFrm;
self.chatImageView.backgroundColor = [UIColor redColor];
// 3.下载图片
NSLog(@"%@",imgBody.thumbnailLocalPath);
NSLog(@"%@",imgBody.thumbnailRemotePath);
// 如果本地图片存在,直接从本地显示图片
NSFileManager *manager = [NSFileManager defaultManager];
UIImage *placeImg = [UIImage imageNamed:@"downloading"];
if ([manager fileExistsAtPath:imgBody.thumbnailLocalPath]) {
[self.chatImageView sd_setImageWithURL:[NSURL fileURLWithPath:imgBody.thumbnailLocalPath]placeholderImage:placeImg];
}else
{
// 如果本地图片不存 从网络加载图片
[self.chatImageView sd_setImageWithURL:[NSURL URLWithString:imgBody.thumbnailRemotePath]placeholderImage:placeImg];
}
}else
{
// 获取图片消息体
EMImageMessageBody *imgBody = self.message.messageBodies[0];
CGRect thumbnailFrm = (CGRect){0,0,imgBody.thumbnailSize};
NSLog(@"%f",thumbnailFrm.size.height);
// 设置Label的尺寸足够显示UIimageView
NSTextAttachment *imgAttach = [[NSTextAttachment alloc]init];
imgAttach.bounds =thumbnailFrm;
// 占位思想
NSAttributedString *imgAtt = [NSAttributedString attributedStringWithAttachment:imgAttach];
self.messaLabel.attributedText = imgAtt;
//1.首先要在cell里面添加一个UIImageView
[self.messaLabel addSubview:self.chatImageView];
// 2.设置图片控件为缩略图的尺寸
self.chatImageView.frame = thumbnailFrm;
self.chatImageView.backgroundColor = [UIColor redColor];
// 3.下载图片
NSLog(@"%@",imgBody.thumbnailLocalPath);
NSLog(@"%@",imgBody.thumbnailRemotePath);
// 如果本地图片存在,直接从本地显示图片
NSFileManager *manager = [NSFileManager defaultManager];
UIImage *placeImg = [UIImage imageNamed:@"downloading"];
if ([manager fileExistsAtPath:imgBody.thumbnailLocalPath]) {
[self.chatImageView sd_setImageWithURL:[NSURL fileURLWithPath:imgBody.thumbnailLocalPath]placeholderImage:placeImg];
}else
{
// 如果本地图片不存 从网络加载图片
[self.chatImageView sd_setImageWithURL:[NSURL URLWithString:imgBody.thumbnailRemotePath]placeholderImage:placeImg];
}
}
}
#pragma mark--返回语音的副文本
- (NSAttributedString *)voiceAtt{
// 创建一个可变的副文本
NSMutableAttributedString *voiceAttM = [[NSMutableAttributedString alloc]init];
if ([self.reuseIdentifier isEqualToString:ReceiveCell]) {
// 接收方 ,富文本 = 图片+时间
UIImage *receiverImg = [UIImage imageNamed:@"chat_receiver_audio_playing_full"];
// 创建一个图片的附件
NSTextAttachment *imgAttachment = [[NSTextAttachment alloc]init];
imgAttachment.image = receiverImg;
imgAttachment.bounds = CGRectMake(0, -7, 30, 30);
// 图片副文本
NSAttributedString *imgAtt = [NSMutableAttributedString attributedStringWithAttachment:imgAttachment];
[voiceAttM appendAttributedString:imgAtt];
// 创建时间的副文本
// 获取时间
EMVoiceMessageBody *voiceBody = self.message.messageBodies[0];
NSInteger duration = voiceBody.duration;
NSString *timeStr = [NSString stringWithFormat:@"%d",duration];
NSAttributedString *timeAtt = [[NSAttributedString alloc]initWithString:timeStr];
[voiceAttM appendAttributedString:timeAtt];
}else
{
// 发送方:副文本 = 时间+图片
// 创建时间的副文本
// 获取时间
EMVoiceMessageBody *voiceBody = self.message.messageBodies[0];
NSInteger duration = voiceBody.duration;
NSString *timeStr = [NSString stringWithFormat:@"%d",duration];
NSAttributedString *timeAtt = [[NSAttributedString alloc]initWithString:timeStr];
[voiceAttM appendAttributedString:timeAtt];
UIImage *receiverImg = [UIImage imageNamed:@"chat_sender_audio_playing_full"];
// 创建一个图片的附件
NSTextAttachment *imgAttachment = [[NSTextAttachment alloc]init];
imgAttachment.image = receiverImg;
imgAttachment.bounds = CGRectMake(0, -7, 30, 30);
// 图片副文本
NSAttributedString *imgAtt = [NSMutableAttributedString attributedStringWithAttachment:imgAttachment];
[voiceAttM appendAttributedString:imgAtt];
}
return [voiceAttM copy];
}
// 返回cell的高度
- (CGFloat)cellHeight:(EMMessage *)message
{
[self setNeedsLayout];
[self layoutIfNeeded];
id body = message.messageBodies[0];
if ([body isKindOfClass:[EMTextMessageBody class]]) {
CGRect tmpRect = [self.messaLabel.text boundingRectWithSize:CGSizeMake(242, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin attributes:[NSDictionary dictionaryWithObjectsAndKeys:[UIFont systemFontOfSize:17],NSFontAttributeName, nil] context:nil];
return 5+10+tmpRect.size.height+10+5;
}else if([body isKindOfClass:[EMVoiceMessageBody class]]){
CGRect tmpRect = [self.messaLabel.text boundingRectWithSize:CGSizeMake(242, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin attributes:[NSDictionary dictionaryWithObjectsAndKeys:[UIFont systemFontOfSize:17],NSFontAttributeName, nil] context:nil];
return 5+10+tmpRect.size.height+10+5;
}else if ([body isKindOfClass:[EMImageMessageBody class]]){
EMImageMessageBody *imgBody = body;
CGRect thumbnailFrm = (CGRect){0,0,imgBody.thumbnailSize};
CGRect tmpRect2= [self.messaLabel.attributedText boundingRectWithSize:thumbnailFrm.size options:NSStringDrawingUsesLineFragmentOrigin context:nil];
return 5+10+tmpRect2.size.height+10+5;
}else{
return 0;
}
//1.重新布局子控件
// [super layoutIfNeeded];
// [self setNeedsLayout];
// [self layoutIfNeeded];
// [self layoutSubviews];
// NSLog(@"%f",self.messaLabel.bounds.size.height);
//// NSLog(@"%@",self.messaLabel.text);
//
// EMImageMessageBody *imgBody = self.message.messageBodies[0];
// CGRect thumbnailFrm = (CGRect){0,0,imgBody.thumbnailSize};
// CGRect tmpRect2= [self.messaLabel.attributedText boundingRectWithSize:thumbnailFrm.size options:NSStringDrawingUsesLineFragmentOrigin context:nil];
//
// CGRect tmpRect = [self.messaLabel.text boundingRectWithSize:CGSizeMake(242, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin attributes:[NSDictionary dictionaryWithObjectsAndKeys:[UIFont systemFontOfSize:17],NSFontAttributeName, nil] context:nil];
//// CGRect tmpRect2 = self.messaLabel.attributedText
//// CGSize temp = [self.messaLabel.text sizeWithFont:[UIFont systemFontOfSize:17] constrainedToSize:CGSizeMake(242, MAXFLOAT)];
//// CGSize temp = [self.messaLabel.text sizeWithAttributes:[NSDictionary dictionaryWithObjectsAndKeys:[UIFont systemFontOfSize:17],NSFontAttributeName,CGSizeMake(242, MAXFLOAT), nil]];
//
//// NSLog(@"----%f",tmpRect.size.height);
//// self.messaLabel.bounds.size.height
//// return 5+10+tmpRect.size.height+10+5;
// return 5+10+tmpRect2.size.height+10+5;
// return 5+10+self.messaLabel.bounds.size.height+10+5;
}
另外一点在计算不同cell高度的时候我选择了不同类型的cell不同的处理,不过用[self.messaLabel.attributedText boundingRectWithSize:thumbnailFrm.size options:NSStringDrawingUsesLineFragmentOrigin context:nil];这个方法还是有缺陷的,它的大小不是原始大小
// Xiaoqiuhuanxin
//