聊天界面一般包含:文字、语音、图片三大部分。
整体的我用的是UITableView,具体聊天的展示是用的cell,把所有视图都放到cell上用到的显示用不到的隐藏。
项目的的编写采用了MVC 模式。所有的界面布局都是在CSMessageModel中完成。先上效果图。
简单来说,我们要根据接收到的数据类型的不同来展示不同的东西。所以我们需要事先和服务器定义好接口协议并把他封装成一个Model。另外还要有时间,以及自己和他人的区别。这些也要一起定义。我的Model类型如下,大家可以根据自己的需要进行添加和删除。
@property (nonatomic, assign) MessageType messageType;//消息类型
@property (nonatomic, assign) MessageSenderType messageSenderType;//自己还是他人
/*
是否显示小时的时间
*/
@property (nonatomic, assign) BOOL showMessageTime;
/*
消息时间 2017-09-11 11:11
*/
@property (nonatomic, retain) NSString *messageTime;
/*
图像url
*/
@property (nonatomic, retain) NSString *logoUrl;
/*
消息文本内容
*/
@property (nonatomic, retain) NSString *messageText;
/*
音频时间
*/
@property (nonatomic, assign) NSInteger duringTime;
/*
消息音频url
*/
@property (nonatomic, retain) NSString *voiceUrl;
/*
图片文件
*/
@property (nonatomic, retain) NSString *imageUrl;
/*
图片文件
*/
@property (nonatomic, retain) UIImage *imageSmall;
然后就是根据上面的类型去定义各自的frame,根据自己的需要进行添加和删除。
- (CGRect)timeFrame;
- (CGRect)logoFrame;
- (CGRect)messageFrame;
- (CGRect)voiceFrame;
- (CGRect)voiceAnimationFrame;
- (CGRect)bubbleFrame;
- (CGRect)imageFrame;
- (CGFloat)cellHeight;
CSMessageModel.m 中实现Frame初始化。举例如下,具体的可以查看demo。
- (CGRect)timeFrame
{
CGRect rect = CGRectZero;
if (self.showMessageTime)//判断要不要展示时间
{
CGSize size = [self labelAutoCalculateRectWith:self.messageTime Font:[UIFont fontWithName:FONT_REGULAR size:10] MaxSize:CGSizeMake(MAXFLOAT, 17)];
rect = CGRectMake((ScreenWidth - size.width)/2, 0, size.width + 10, 17);
}
return rect;
}
- (CGRect)logoFrame
{
CGRect timeRect = [self timeFrame];
CGRect rect = CGRectZero;
if (self.messageSenderType == MessageSenderTypeMe)//判断是自己还是别人
{
rect = CGRectMake(ScreenWidth - 50,timeRect.size.height + 10, 40, 40);
}
else
{
rect = CGRectMake(10, timeRect.size.height + 10, 40, 40);
}
return rect;
}
然后就是自定义cell
直接传Model进来
+(instancetype)cellWithTableView:(UITableView *)tableView messageModel:(CSMessageModel *)model;
重点在要根据Model去计算布局
- (void)setMessageModel:(CSMessageModel *)messageModel {
_messageModel = messageModel;
_timeLabel.hidden = !messageModel.showMessageTime;
_timeLabel.frame = [messageModel timeFrame];
_timeLabel.text = messageModel.messageTime;
_logoImageView.hidden = NO;
_logoImageView.frame = [messageModel logoFrame];
_bubbleImageView.hidden = NO;
_bubbleImageView.frame = [messageModel bubbleFrame];
if (messageModel.messageSenderType == MessageSenderTypeMe)
{
_logoImageView.image = [UIImage imageNamed:@"w"];
_bubbleImageView.image = [[UIImage imageNamed:@"me"] stretchableImageWithLeftCapWidth:20 topCapHeight:40];
}
else
{
_logoImageView.image = [UIImage imageNamed:@"m"];
_bubbleImageView.image = [[UIImage imageNamed:@"other"] stretchableImageWithLeftCapWidth:20 topCapHeight:40];
}
switch (messageModel.messageType)
{
case MessageTypeText:
_messageLabel.hidden = NO;
_messageLabel.frame = [messageModel messageFrame];
_messageLabel.text = messageModel.messageText;
_messageLabel.textAlignment = NSTextAlignmentLeft;
break;
case MessageTypeVoice:
_voiceImageView.hidden = NO;
_voiceImageView.frame = [messageModel voiceFrame];
_messageLabel.hidden = NO;
_messageLabel.frame = [messageModel voiceFrame];
_messageLabel.textAlignment = messageModel.messageSenderType == MessageSenderTypeMe ? NSTextAlignmentLeft:NSTextAlignmentRight;
_messageLabel.text = [NSString stringWithFormat:@"%ld''",(long)messageModel.duringTime];
_voiceAnimationImageView.hidden = NO;
_voiceAnimationImageView.frame = [messageModel voiceAnimationFrame];
_voiceAnimationImageView.image=[UIImage imageNamed:@"wechatvoice3"];
_voiceAnimationImageView.animationImages = [NSArray arrayWithObjects:[UIImage imageNamed:@"wechatvoice3"],[UIImage imageNamed:@"wechatvoice3_1"],[UIImage imageNamed:@"wechatvoice3_0"],[UIImage imageNamed:@"wechatvoice3_1"],[UIImage imageNamed:@"wechatvoice3"],nil];
_voiceAnimationImageView.animationDuration = 1;
_voiceAnimationImageView.transform =messageModel.messageSenderType == MessageSenderTypeMe ? CGAffineTransformMakeRotation(M_PI) : CGAffineTransformMakeRotation(0);
_voiceAnimationImageView.animationRepeatCount = -1;
break;
case MessageTypeImage:
_imageImageView.hidden = NO;
_imageImageView.frame = [messageModel imageFrame];
_imageImageView.image = messageModel.imageSmall;
CGSize imageSize = [messageModel.imageSmall imageShowSize];
UIImageView *imageViewMask = [[UIImageView alloc] initWithImage:[[UIImage imageNamed:_messageModel.messageSenderType == MessageSenderTypeMe ? @"me" :@"other"] stretchableImageWithLeftCapWidth:20 topCapHeight:40]];
imageViewMask.frame = CGRectMake(0, 0, imageSize.width, imageSize.height);
_imageImageView.layer.mask = imageViewMask.layer;
break;
// default:
// break;
}
}
最后在调用
model = [[CSMessageModel alloc] init];
model.showMessageTime=YES;
model.messageSenderType = MessageSenderTypeOther;
model.messageType = MessageTypeText;
model.messageText = @"我们都一样";
model.messageTime = @"16:40";
[_dataArray addObject:model];
至此聊天界面完成。
另外添加了表情和语音。
注:发送图片和语音的时候,服务器我们这里用了base64进行的加密。转换成了二进制流。图片和语音要问清楚服务器支持多大的。要进行压缩。