IOS 仿微信聊天界面
2016-11-22 20:22
417 查看
本来没有打算写这篇日志的,但是的确没有一个网友写的仿微信争气,大部分是过度封装,别人无法复用或在其基础上改动,那么这个就尴尬了。。。大神都把B装了,但是让我们理解大神的想法,额,这个有难度。。。 一气之下花了一天的时间自己搞了一把,不说神似吧,至少形似,好吧,上图!
其实 我已经把项目上传到了github, BUT, 我大天朝的网络,特别是上外网,好吧,不黑了,程序猿都懂得。
github地址:https://github.com/hebiao6446/HeBiaoWeChat
虽然项目我已经发布了,但是我还是要说两句,那就是本人的思路。
第一点:建立Model对象
为什么要建立Model对象,其实如果你牛逼的话,用字典也是可以的,但是我不算很牛逼,所以我建对象,数据类型有个大概的了解
聊天很明显发生在两个人(群聊忽略)之间,那么这个对象应该有那一边发送消息的属性;然后就是消息类型:是纯字符消息,还是语音消息,还是图片消息(其他忽略,你花一天时间做出来的功能干的过人家企鹅吗?别不自量力少年),然后就是消息发送状态,还有已读未读(我们APP的需求)
我写的这个 聊天的Model一共包括以下属性: 消息类型,消息发送方,消息发送状态,消息读取状态,是否显示时间,消息发送时间,用户图像url,消息文本内容,音频持续时间,音频url,高清图url,低清图UIImage
代码奉上:
第二点:建立Cell对象
这个就不用废话了,你不建对象你试试?
我这个Cell对象是根据Model来生成的,那么同样的,cell的高度也是根据Model来决定的,那么可以这样写
说到列表高度,我不得不说一下, 我们知道消息分为纯文本,语音,图片三种,文本的高度是根据文字的多少计算的,语音高度是确定的,图片的高度这里要说下了:图片有可能是横向也有可能是纵向,但是图片有个最大宽度或最大高度,这个是通过微信APP截屏计算的。
刚刚说到了图片的宽度,我们知道音频的长度是不一样的,并且音频有最大长度和最小长度
同样,我也是通过微信APP截屏然后拉进PS中你懂得。。。
那么文本的高度怎么计算了 ?问题来了,因为文本字数可能多,可能少,而且有最大宽度,最变态的是,文本的最大宽度在不同的手机上是不一样的,来自微信截频
而且左右两边的宽度不一样 。 好不,直接上代码了
说到这里你可能有点懵。。。 我们来张图
其实各种加减法都是移动位置,让显示最好看, 我们需要对底图进行拉伸,关于iOS的图片拉伸,这里就不说了,不懂百度去。。 底图是一个UIImageView,然后把内容放在UIImageView上,包括文字,图片,甚至是声音的动画效果。
说几个蛋疼的地方:
蛋疼A: cell有好几个事件, 点击,双击,长按,这些都是通过手势来完成的,而且都是加载这个底部的UIImageView上的。
蛋疼B:当长按cell的时候会出现阴影,如果你用button是可以出现阴影的,但是有很多手势事件,如果用button ,你试试,反正我是把button改为UIImageview的,这个阴影怎么来的 ? 其实是底图上铺上了一层一模一样大的图片,ps修改透明度 ,图如下
长按会出现阴影,其实在底图上加了一层阴影,其实每个cell又有阴影,只不过一开始都隐藏了。。。 要知道,实现这个功能多不容易
蛋疼C:UIMenuController 的使用,这哥们是一个单例的对象,所以也注定你在隐藏着哥们的时候注意了。。你在滚动列表的时候这哥们需要隐藏,然后在点击其他cell或者本cell的时候也需要隐藏,并且这哥们隐藏的时候会发出通知的:
所以这哥们隐藏了,你覆盖在底图的覆盖图也应该隐藏。。
蛋疼D: 音频播放的动画,获取你在csdn上看不到,你可以到github上看:https://github.com/hebiao6446/HeBiaoWeChat
蛋疼的动画,而且点击的瞬间覆盖物要显示下
这上面也许看不见。。
蛋疼E: 各种发送状态,这个不解释了 。。
好吧,附上代码, 如果没有资源文件,去github下载下, 另外,我使用了cocoapods导入的第三方包,不熟悉的同学面壁思过去。。。定义了一个block
说到block,我又想起几个比较2的面试官,问我block和代理的区别,block和代理都能实现的东西,有什么区别?能做出来,不出错,稳定就行,尽管block是潮流,但是代理强迫症人比较喜欢。这个项目没有用代理,如果面试官有幸看到这篇博客自己去想去吧!
实现类睁大眼睛了 。。。
引用这个Cell 是比较容易的 。。
代码还是贴上吧。 。
定义的宏
然后是cell的调用
调用很简单。。。 如果你不明白还是 上github下载下来搞一搞
https://github.com/hebiao6446/HeBiaoWeChat
其实 我已经把项目上传到了github, BUT, 我大天朝的网络,特别是上外网,好吧,不黑了,程序猿都懂得。
github地址:https://github.com/hebiao6446/HeBiaoWeChat
虽然项目我已经发布了,但是我还是要说两句,那就是本人的思路。
第一点:建立Model对象
为什么要建立Model对象,其实如果你牛逼的话,用字典也是可以的,但是我不算很牛逼,所以我建对象,数据类型有个大概的了解
聊天很明显发生在两个人(群聊忽略)之间,那么这个对象应该有那一边发送消息的属性;然后就是消息类型:是纯字符消息,还是语音消息,还是图片消息(其他忽略,你花一天时间做出来的功能干的过人家企鹅吗?别不自量力少年),然后就是消息发送状态,还有已读未读(我们APP的需求)
我写的这个 聊天的Model一共包括以下属性: 消息类型,消息发送方,消息发送状态,消息读取状态,是否显示时间,消息发送时间,用户图像url,消息文本内容,音频持续时间,音频url,高清图url,低清图UIImage
代码奉上:
#import <UIKit/UIKit.h> /* 消息类型 */ typedef NS_OPTIONS(NSUInteger, MessageType) { MessageTypeText=1, MessageTypeVoice, MessageTypeImage }; /* 消息发送方 */ typedef NS_OPTIONS(NSUInteger, MessageSenderType) { MessageSenderTypeHantu=1, MessageSenderTypeUser }; /* 消息发送状态 */ typedef NS_OPTIONS(NSUInteger, MessageSentStatus) { MessageSentStatusSended=1,//送达 MessageSentStatusUnSended, //未发送 MessageSentStatusSending, //正在发送 }; /* 消息接收状态 */ typedef NS_OPTIONS(NSUInteger, MessageReadStatus) { MessageReadStatusRead=1,//消息已读 MessageReadStatusUnRead //消息未读 }; /* 只有当消息送达的时候,才会出现 接收状态, 消息已读 和未读 仅仅针对自己 未送达显示红色, 发送中显示菊花 送达状态彼此互斥 */ @interface MessageModel : NSObject @property (nonatomic, assign) MessageType messageType; @property (nonatomic, assign) MessageSenderType messageSenderType; @property (nonatomic, assign) MessageSentStatus messageSentStatus; @property (nonatomic, assign) MessageReadStatus messageReadStatus; /* 是否显示小时的时间 */ @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; @end
第二点:建立Cell对象
这个就不用废话了,你不建对象你试试?
我这个Cell对象是根据Model来生成的,那么同样的,cell的高度也是根据Model来决定的,那么可以这样写
@interface WeChatCell : UITableViewCell +(instancetype)cellWithTableView:(UITableView *)tableView messageModel:(MessageModel *)model; +(CGFloat)tableHeightWithModel:(MessageModel *)model; @end
说到列表高度,我不得不说一下, 我们知道消息分为纯文本,语音,图片三种,文本的高度是根据文字的多少计算的,语音高度是确定的,图片的高度这里要说下了:图片有可能是横向也有可能是纵向,但是图片有个最大宽度或最大高度,这个是通过微信APP截屏计算的。
/* 判断图片长度&宽度 */ +(CGSize)imageShowSize:(UIImage *)image{ CGFloat imageWith=image.size.width; CGFloat imageHeight=image.size.height; //宽度大于高度 if (imageWith>=imageHeight) { // 宽度超过标准宽度 /* if (imageWith>MAX_IMAGE_WH) { }else{ } */ return CGSizeMake(MAX_IMAGE_WH, imageHeight*MAX_IMAGE_WH/imageWith); }else{ /* if (imageHeight>MAX_IMAGE_WH) { }else{ } */ return CGSizeMake(imageWith*MAX_IMAGE_WH/imageHeight, MAX_IMAGE_WH); } return CGSizeZero; }
刚刚说到了图片的宽度,我们知道音频的长度是不一样的,并且音频有最大长度和最小长度
同样,我也是通过微信APP截屏然后拉进PS中你懂得。。。
-(CGFloat)voiceLength:(NSInteger)seconds{ if (seconds==0) { return 75; } // 6~197 6p~230 // 75 CGFloat max=AppFrameWidth>750?230:197; return 75+(seconds-1)*(max-75)*1.0/60.0; }
那么文本的高度怎么计算了 ?问题来了,因为文本字数可能多,可能少,而且有最大宽度,最变态的是,文本的最大宽度在不同的手机上是不一样的,来自微信截频
而且左右两边的宽度不一样 。 好不,直接上代码了
#define LEFT_WITH (AppFrameWidth>750?55:52.5) #define RIGHT_WITH (AppFrameWidth>750?89:73) CGFloat maxWith=AppFrameWidth-LEFT_WITH-RIGHT_WITH-14-12-4; UIFont *textFont=[UIFont fontWithName:FONT_REGULAR size:16]; CGRect rect = [model.messageText boundingRectWithSize:CGSizeMake(maxWith, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin attributes:attributes context:nil]; contextBack.frame=CGRectMake(LEFT_WITH, masTop, rect.size.width+26, rect.size.height+26);
说到这里你可能有点懵。。。 我们来张图
其实各种加减法都是移动位置,让显示最好看, 我们需要对底图进行拉伸,关于iOS的图片拉伸,这里就不说了,不懂百度去。。 底图是一个UIImageView,然后把内容放在UIImageView上,包括文字,图片,甚至是声音的动画效果。
说几个蛋疼的地方:
蛋疼A: cell有好几个事件, 点击,双击,长按,这些都是通过手势来完成的,而且都是加载这个底部的UIImageView上的。
蛋疼B:当长按cell的时候会出现阴影,如果你用button是可以出现阴影的,但是有很多手势事件,如果用button ,你试试,反正我是把button改为UIImageview的,这个阴影怎么来的 ? 其实是底图上铺上了一层一模一样大的图片,ps修改透明度 ,图如下
长按会出现阴影,其实在底图上加了一层阴影,其实每个cell又有阴影,只不过一开始都隐藏了。。。 要知道,实现这个功能多不容易
蛋疼C:UIMenuController 的使用,这哥们是一个单例的对象,所以也注定你在隐藏着哥们的时候注意了。。你在滚动列表的时候这哥们需要隐藏,然后在点击其他cell或者本cell的时候也需要隐藏,并且这哥们隐藏的时候会发出通知的:
UIKIT_EXTERN NSNotificationName const UIMenuControllerWillShowMenuNotification __TVOS_PROHIBITED; UIKIT_EXTERN NSNotificationName const UIMenuControllerDidShowMenuNotification __TVOS_PROHIBITED; UIKIT_EXTERN NSNotificationName const UIMenuControllerWillHideMenuNotification __TVOS_PROHIBITED; UIKIT_EXTERN NSNotificationName const UIMenuControllerDidHideMenuNotification __TVOS_PROHIBITED; UIKIT_EXTERN NSNotificationName const UIMenuControllerMenuFrameDidChangeNotification __TVOS_PROHIBITED;
所以这哥们隐藏了,你覆盖在底图的覆盖图也应该隐藏。。
蛋疼D: 音频播放的动画,获取你在csdn上看不到,你可以到github上看:https://github.com/hebiao6446/HeBiaoWeChat
蛋疼的动画,而且点击的瞬间覆盖物要显示下
这上面也许看不见。。
蛋疼E: 各种发送状态,这个不解释了 。。
好吧,附上代码, 如果没有资源文件,去github下载下, 另外,我使用了cocoapods导入的第三方包,不熟悉的同学面壁思过去。。。定义了一个block
说到block,我又想起几个比较2的面试官,问我block和代理的区别,block和代理都能实现的东西,有什么区别?能做出来,不出错,稳定就行,尽管block是潮流,但是代理强迫症人比较喜欢。这个项目没有用代理,如果面试官有幸看到这篇博客自己去想去吧!
#import <UIKit/UIKit.h> @class MessageModel; typedef void (^DoubleClickBlock) (MessageModel * model); @interface WeChatCell : UITableViewCell +(instancetype)cellWithTableView:(UITableView *)tableView messageModel:(MessageModel *)model; +(CGFloat)tableHeightWithModel:(MessageModel *)model; @property (nonatomic,strong) UIImageView* voiceAnimationImageView; @property (nonatomic,strong) UIImageView* coversImageView; @property (nonatomic,strong) MessageModel* messageModel; @property(nonatomic,copy)DoubleClickBlock doubleblock; @property(nonatomic,copy)DoubleClickBlock singleblock; @property(nonatomic,copy)DoubleClickBlock resendblock; -(void)setDoubleClickBlock:(DoubleClickBlock )doubleClickBlock; -(void)setSingleClickBlock:(DoubleClickBlock )singleClickBlock; -(void)setResendClickBlock:(DoubleClickBlock )resendClickBlock; -(void)stopVoiceAnimation; -(void)startVoiceAnimation; -(void)startSentMessageAnimation; -(void)stopSentMessageAnimation; @end
实现类睁大眼睛了 。。。
#import "WeChatCell.h"
#import "MessageModel.h"
#import "Masonry.h"
#import "ConstantPart.h"
#import "AFNetworking.h"
#import "UIKit+AFNetworking.h"
#define LEFT_WITH (AppFrameWidth>750?55:52.5)
#define RIGHT_WITH (AppFrameWidth>750?89:73)
// 1s length 75
// 60s 6~197 6p~230
#define MAX_IMAGE_WH 141.0
#define DEF_ICON @"collection4_10"
@implementation WeChatCell
+(instancetype)cellWithTableView:(UITableView *)tableView messageModel:(MessageModel *)model{
static NSString *identifier = @"WeChatCell";
WeChatCell *cell=[tableView dequeueReusableCellWithIdentifier:identifier];
if (cell!=nil) {
cell=nil;
}
cell = [[WeChatCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier messageModel:model];
return cell;
}
-(id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier messageModel:(MessageModel *)model{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
self.selectionStyle=UITableViewCellSelectionStyleNone;
self.messageModel=model;
for (UIView *v in [self.contentView subviews]) {
[v removeFromSuperview];
}
CGFloat masTop=10;
if (model.showMessageTime) {
masTop=37;
UILabel *timeLabel=[[UILabel alloc] init];
timeLabel.font=[UIFont fontWithName:FONT_REGULAR size:10];
timeLabel.backgroundColor=COLOR_cecece;
timeLabel.textColor=COLOR_ffffff;
timeLabel.text=model.messageTime;
timeLabel.textAlignment=NSTextAlignmentCenter;
timeLabel.layer.masksToBounds=YES;
timeLabel.layer.cornerRadius=4;
timeLabel.layer.borderColor=[COLOR_cecece CGColor];
timeLabel.layer.borderWidth=1;
[self.contentView addSubview:timeLabel];
[timeLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.mas_equalTo(self.contentView.mas_top).offset(10);
make.centerX.equalTo(self.contentView);
make.width.mas_equalTo(40);
make.height.mas_equalTo(17);
}];
}
UIImageView *contextBack=[[UIImageView alloc] init];
contextBack.userInteractionEnabled=YES;
self.coversImageView=[[UIImageView alloc] init];
self.coversImageView.userInteractionEnabled=YES;
if (model.messageType==MessageTypeText) {
// 是用户 还是韩图客服
if (model.messageSenderType==MessageSenderTypeHantu) {
UIImageView *logoImage=[[UIImageView alloc] init];
logoImage.frame=CGRectMake(10, masTop, 40, 40);
[logoImage setImageWithURL:[NSURL URLWithString:model.logoUrl] placeholderImage:[UIImage imageNamed:DEF_ICON]];
[self.contentView addSubview:logoImage];
CGFloat maxWith=AppFrameWidth-LEFT_WITH-RIGHT_WITH-14-12-4;
UIFont *textFont=[UIFont fontWithName:FONT_REGULAR size:16];
NSDictionary *attributes = @{NSFontAttributeName: textFont};
CGRect rect = [model.messageText boundingRectWithSize:CGSizeMake(maxWith, MAXFLOAT)
options:NSStringDrawingUsesLineFragmentOrigin
attributes:attributes
context:nil];
contextBack.frame=CGRectMake(LEFT_WITH, masTop, rect.size.width+26, rect.size.height+26);
contextBack.image=[[UIImage imageNamed:@"wechatback1"] stretchableImageWithLeftCapWidth:10 topCapHeight:25];
[self.contentView addSubview:contextBack];
UILabel *textMessageLabel=[[UILabel alloc] init];
textMessageLabel.frame=CGRectMake(LEFT_WITH+12, masTop+14, rect.size.width, rect.size.height);
textMessageLabel.numberOfLines=0;
textMessageLabel.lineBreakMode=NSLineBreakByWordWrapping;
textMessageLabel.font=textFont;
textMessageLabel.textColor=COLOR_444444;
textMessageLabel.text=model.messageText;
[self.contentView addSubview:textMessageLabel];
}else if (model.messageSenderType==MessageSenderTypeUser){
UIImageView *logoImage=[[UIImageView alloc] init];
logoImage.frame=CGRectMake(AppFrameWidth-10-40, masTop, 40, 40);
[logoImage setImageWithURL:[NSURL URLWithString:model.logoUrl] placeholderImage:[UIImage imageNamed:DEF_ICON]];
[self.contentView addSubview:logoImage];
CGFloat maxWith=AppFrameWidth-LEFT_WITH-RIGHT_WITH-14-12-4;
UIFont *textFont=[UIFont fontWithName:FONT_REGULAR size:16];
NSDictionary *attributes = @{NSFontAttributeName: textFont};
CGRect rect = [model.messageText boundingRectWithSize:CGSizeMake(maxWith, MAXFLOAT)
options:NSStringDrawingUsesLineFragmentOrigin
attributes:attributes
context:nil];
contextBack.frame=CGRectMake(AppFrameWidth-(rect.size.width+26)-LEFT_WITH, masTop, rect.size.width+26, rect.size.height+26);
contextBack.image=[[UIImage imageNamed:@"wechatback2"] stretchableImageWithLeftCapWidth:10 topCapHeight:25];
[self.contentView addSubview:contextBack];
UILabel *textMessageLabel=[[UILabel alloc] init];
textMessageLabel.frame=CGRectMake(AppFrameWidth-(rect.size.width+26)-LEFT_WITH+12, masTop+14, rect.size.width, rect.size.height);
textMessageLabel.numberOfLines=0;
textMessageLabel.lineBreakMode=NSLineBreakByWordWrapping;
textMessageLabel.font=textFont;
textMessageLabel.textColor=COLOR_444444;
textMessageLabel.text=model.messageText;
[self.contentView addSubview:textMessageLabel];
}
}else if (model.messageType==MessageTypeVoice){
self.voiceAnimationImageView=[[UIImageView alloc] init];
self.voiceAnimationImageView.animationRepeatCount = 0;
self.voiceAnimationImageView.animationDuration = 2;
// 是用户 还是韩图客服
if (model.messageSenderType==MessageSenderTypeHantu) {
UIImageView *logoImage=[[UIImageView alloc] init];
logoImage.frame=CGRectMake(10, masTop, 40, 40);
[logoImage setImageWithURL:[NSURL URLWithString:model.logoUrl] placeholderImage:[UIImage imageNamed:DEF_ICON]];
[self.contentView addSubview:logoImage];
contextBack.frame=CGRectMake(LEFT_WITH, masTop, [self voiceLength:model.duringTime], 40);
contextBack.image=[[UIImage imageNamed:@"wechatback1"] stretchableImageWithLeftCapWidth:10 topCapHeight:25];
// textBackImage.userInteractionEnabled=YES;
[self.contentView addSubview:contextBack];
self.voiceAnimationImageView.frame=CGRectMake(12, 12, 12, 16);
self.voiceAnimationImageView.image=[UIImage imageNamed:@"wechatvoice3"];
self.voiceAnimationImageView.animationImages=[NSArray arrayWithObjects:[UIImage imageNamed:@"wechatvoice3"],[UIImage imageNamed:@"wechatvoice3_1"],[UIImage imageNamed:@"wechatvoice3_0"],[UIImage imageNamed:@"wechatvoice3_1"],[UIImage imageNamed:@"wechatvoice3"],nil];
[contextBack addSubview:self.voiceAnimationImageView];
}else if (model.messageSenderType==MessageSenderTypeUser){
UIImageView *logoImage=[[UIImageView alloc] init];
logoImage.frame=CGRectMake(AppFrameWidth-10-40, masTop, 40, 40);
[logoImage setImageWithURL:[NSURL URLWithString:model.logoUrl] placeholderImage:[UIImage imageNamed:DEF_ICON]];
[self.contentView addSubview:logoImage];
contextBack.frame=CGRectMake(AppFrameWidth-LEFT_WITH-[self voiceLength:model.duringTime], masTop, [self voiceLength:model.duringTime], 40);
contextBack.image=[[UIImage imageNamed:@"wechatback2"] stretchableImageWithLeftCapWidth:10 topCapHeight:25];
[self.contentView addSubview:contextBack];
self.voiceAnimationImageView.frame=CGRectMake([self voiceLength:model.duringTime]-12-11, 12, 11, 16);
self.voiceAnimationImageView.image=[UIImage imageNamed:@"wechatvoice4"];
self.voiceAnimationImageView.animationImages=[NSArray arrayWithObjects:[UIImage imageNamed:@"wechatvoice4"],[UIImage imageNamed:@"wechatvoice4_1"],[UIImage imageNamed:@"wechatvoice4_0"],[UIImage imageNamed:@"wechatvoice4_1"],[UIImage imageNamed:@"wechatvoice4"],nil];
[contextBack addSubview:self.voiceAnimationImageView];
}
}else if (model.messageType==MessageTypeImage){
// 是用户 还是韩图客服
if (model.messageSenderType==MessageSenderTypeHantu) {
UIImageView *logoImage=[[UIImageView alloc] init];
logoImage.frame=CGRectMake(10, masTop, 40, 40);
[logoImage setImageWithURL:[NSURL URLWithString:model.logoUrl] placeholderImage:[UIImage imageNamed:DEF_ICON]];
[self.contentView addSubview:logoImage];
CGSize imageSize=[WeChatCell imageShowSize:model.imageSmall];
UIImageView *imageViewMask = [[UIImageView alloc] initWithImage:[[UIImage imageNamed:@"wechatback1"] stretchableImageWithLeftCapWidth:10 topCapHeight:25]];
imageViewMask.frame = CGRectMake(0, 0, imageSize.width, imageSize.height);
contextBack.frame=CGRectMake(LEFT_WITH, masTop, imageSize.width, imageSize.height);
contextBack.image=model.imageSmall;
contextBack.layer.mask = imageViewMask.layer;
[self.contentView addSubview:contextBack];
}else if (model.messageSenderType==MessageSenderTypeUser){
UIImageView *logoImage=[[UIImageView alloc] init];
logoImage.frame=CGRectMake(AppFrameWidth-10-40, masTop, 40, 40);
[logoImage setImageWithURL:[NSURL URLWithString:model.logoUrl] placeholderImage:[UIImage imageNamed:DEF_ICON]];
[self.contentView addSubview:logoImage];
CGSize imageSize=[WeChatCell imageShowSize:model.imageSmall];
UIImageView *imageViewMask = [[UIImageView alloc] initWithImage:[[UIImage imageNamed:@"wechatback2"] stretchableImageWithLeftCapWidth:10 topCapHeight:25]];
imageViewMask.frame = CGRectMake(0, 0, imageSize.width, imageSize.height);
contextBack.frame=CGRectMake(AppFrameWidth-LEFT_WITH-imageSize.width, masTop, imageSize.width, imageSize.height);
contextBack.image=model.imageSmall;
contextBack.layer.mask = imageViewMask.layer;
[self.contentView addSubview:contextBack];
}
}
UILongPressGestureRecognizer *longPressGesture=[[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPressBubbleView:)];
[contextBack addGestureRecognizer:longPressGesture];
UITapGestureRecognizer * singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleSingleTap:)];
UITapGestureRecognizer * doubleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleDoubleTap:)];
[doubleTap setNumberOfTapsRequired:2];
[singleTap requireGestureRecognizerToFail:doubleTap];
[contextBack addGestureRecognizer:doubleTap];
[contextBack addGestureRecognizer:singleTap];
self.coversImageView.frame=contextBack.frame;
if (model.messageSenderType==MessageSenderTypeHantu) {
self.coversImageView.image=[[UIImage imageNamed:@"wechatback1cover"] stretchableImageWithLeftCapWidth:10 topCapHeight:25];
}else{
self.coversImageView.image=[[UIImage imageNamed:@"wechatback2cover"] stretchableImageWithLeftCapWidth:10 topCapHeight:25];
}
[self.contentView addSubview:self.coversImageView];
self.coversImageView.hidden=YES;
UITapGestureRecognizer * singleTap2 = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleSingleTap2:)];
[self.coversImageView addGestureRecognizer:singleTap2];
if (model.messageSenderType==MessageSenderTypeUser) {
/// 送达状态仅仅针对 用户
// 只有送达成功 才会出现 已读 和 未读的情况 text
if (model.messageSentStatus==MessageSentStatusSended) {
UILabel *readStatusLabel=[[UILabel alloc] init];
readStatusLabel.font=[UIFont fontWithName:FONT_REGULAR size:12];
if (model.messageReadStatus==MessageReadStatusRead) {
readStatusLabel.text=@"已读";
readStatusLabel.textColor=COLOR_bababa;
}else if (model.messageReadStatus==MessageReadStatusUnRead){
readStatusLabel.text=@"未读";
readStatusLabel.textColor=COLOR_c00000;
}
[self.contentView addSubview:readStatusLabel];
if (model.messageType==MessageTypeVoice) {
UILabel *seconds=[[UILabel alloc] init];
seconds.textColor=COLOR_999999;
seconds.font=[UIFont fontWithName:FONT_REGULAR size:15];
seconds.text=[NSString stringWithFormat:@"%d ''",model.duringTime];
[self.contentView addSubview:seconds];
[seconds mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerY.equalTo(contextBack);
make.right.mas_equalTo(contextBack.mas_left).offset(-10);;
}];
[readStatusLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerY.equalTo(contextBack);
make.right.mas_equalTo(seconds.mas_left).offset(-10);;
}];
}else{
[readStatusLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerY.equalTo(contextBack);
make.right.mas_equalTo(contextBack.mas_left).offset(-10);;
}];
}
}else if(model.messageSentStatus==MessageSentStatusUnSended){
UIButton *unsendButton=[[UIButton alloc] init];
[unsendButton setImage:[UIImage imageNamed:@"wechat_resendbut5"] forState:UIControlStateNormal];
[unsendButton addTarget:self action:@selector(reSendAction:) forControlEvents:UIControlEventTouchUpInside];
[self.contentView addSubview:unsendButton];
if (model.messageType==MessageTypeVoice) {
UILabel *seconds=[[UILabel alloc] init];
seconds.textColor=COLOR_999999;
seconds.font=[UIFont fontWithName:FONT_REGULAR size:15];
seconds.text=[NSString stringWithFormat:@"%d ''",model.duringTime];
[self.contentView addSubview:seconds];
[seconds mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerY.equalTo(contextBack);
make.right.mas_equalTo(contextBack.mas_left).offset(-10);;
}];
[unsendButton mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerY.equalTo(contextBack);
make.right.mas_equalTo(seconds.mas_left).offset(-10);;
}];
}else{
[unsendButton mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerY.equalTo(contextBack);
make.right.mas_equalTo(contextBack.mas_left).offset(-10);;
}];
}
}else if(model.messageSentStatus==MessageSentStatusSending){
UIActivityIndicatorView *acview=[[UIActivityIndicatorView alloc] init];
[acview setActivityIndicatorViewStyle:UIActivityIndicatorViewStyleGray];
[self.contentView addSubview:acview];
[acview mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerY.equalTo(contextBack);
make.right.mas_equalTo(contextBack.mas_left).offset(-10);;
}];
[acview startAnimating];
}
}
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(menuCotrollerWillHidden:) name:UIMenuControllerWillHideMenuNotification object:nil];
// [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(menuCotrollerDidHidden:) name:UIMenuControllerDidHideMenuNotification object:nil];
}
return self;
}
-(void)reSendAction:(UIButton *)sender{
if (self.resendblock) {
self.resendblock(self.messageModel);
}
}
-(void)handleSingleTap2:(id)sender{
self.coversImageView.hidden=YES;
// [ setMenuVisible:YES animated:NO];
if ([UIMenuController sharedMenuController].isMenuVisible) {
[UIMenuController sharedMenuController].menuVisible=NO;
}
}
-(void)menuCotrollerWillHidden:(id)sender{
if (!self.coversImageView.isHidden) {
self.coversImageView.hidden=YES;
}
}
//-(void)menuCotrollerDidHidden:(id)sender{
// NSLog(@"======###############==");
//}
-(void)setResendClickBlock:(DoubleClickBlock )resendClickBlock{
self.resendblock=resendClickBlock;
}
-(void)setSingleClickBlock:(DoubleClickBlock )singleClickBlock{
self.singleblock=singleClickBlock;
}
-(void)setDoubleClickBlock:(DoubleClickBlock )doubleClickBlock{
self.doubleblock=doubleClickBlock;
}
-(void)handleDoubleTap:(id)sender{
if (self.messageModel.messageType==MessageTypeText) {
if (self.doubleblock) {
self.doubleblock(self.messageModel);
}
}
}
-(void)handleSingleTap:(id)sender{
if (self.messageModel.messageType!=MessageTypeText) {
if (self.singleblock) {
self.singleblock(self.messageModel);
}
if (self.messageModel.messageType==MessageTypeVoice) {
[self startVoiceAnimation];
__block WeChatCell/*主控制器*/ *weakSelf = self;
self.coversImageView.hidden=NO;
dispatch_time_t delayTime1 = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC));
dispatch_after(delayTime1, dispatch_get_main_queue(), ^{
self.coversImageView.hidden=YES;
});
dispatch_time_t delayTime2 = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(self.messageModel.duringTime * NSEC_PER_SEC));
dispatch_after(delayTime2, dispatch_get_main_queue(), ^{
[weakSelf stopVoiceAnimation];
});
}
}
}
#pragma 长按事件
- (void)longPressBubbleView:(UILongPressGestureRecognizer *)sender {
if (sender.state == UIGestureRecognizerStateBegan) {
[self showMenuControllerInView:self bgView:sender.view];
}
}
- (void)showMenuControllerInView:(WeChatCell *)inView
bgView:(UIView *)supView
{
self.coversImageView.hidden=NO;
[self becomeFirstResponder];
MessageModel *messageModel=self.messageModel;
UIMenuItem *copyTextItem1 = [[UIMenuItem alloc] initWithTitle:@"复制" action:@selector(copyTextSender1:)];
UIMenuItem *copyTextItem2 = [[UIMenuItem alloc] initWithTitle:@"删除" action:@selector(copyTextSender2:)];
UIMenuItem *copyTextItem3 = [[UIMenuItem alloc] initWithTitle:@"保存" action:@selector(copyTextSender2:)];
UIMenuController *menu = [UIMenuController sharedMenuController];
[menu setTargetRect:supView.frame inView:inView];
[menu setArrowDirection:UIMenuControllerArrowDefault];
if (messageModel.messageType==MessageTypeText) {
[menu setMenuItems:@[copyTextItem1,copyTextItem2,copyTextItem3]];
}else if (messageModel.messageType==MessageTypeImage){
[menu setMenuItems:@[copyTextItem1,copyTextItem2,copyTextItem3]];
}else if(messageModel.messageType==MessageTypeVoice){
[menu setMenuItems:@[copyTextItem1,copyTextItem2,copyTextItem3]];
}
[menu setMenuVisible:YES animated:YES];
}
#pragma mark 剪切板代理方法
-(BOOL)canBecomeFirstResponder {
return YES;
}
-(BOOL)canPerformAction:(SEL)action withSender:(id)sender {
if (action == @selector(copyTextSender1:)) {
return true;
} else if (action == @selector(copyTextSender2:)) {
return true;
} else {
return false;
}
}
-(void)copyTextSender1:(id)sender {
UIPasteboard *pasteboard=[UIPasteboard generalPasteboard];
// pasteboard.string = copiedText;
// [self.chatCellDelegate showToastViewInCell:self toastText:[MQBundleUtil localizedStringForKey:@"save_text_success"]];
}
-(void)copyTextSender2:(id)sender {
UIPasteboard *pasteboard=[UIPasteboard generalPasteboard];
// pasteboard.string = copiedText;
// [self.chatCellDelegate showToastViewInCell:self toastText:[MQBundleUtil localizedStringForKey:@"save_text_success"]];
}
-(void)copyImageSender:(id)sender {
// UIImageWriteToSavedPhotosAlbum(copiedImage, self, @selector(image:didFinishSavingWithError:contextInfo:), NULL);
}
//保存到相册的回调
- (void)image:(UIImage *)image
didFinishSavingWithError:(NSError *)error
contextInfo:(void *)contextInfo
{
if(error != NULL){
// [self.chatCellDelegate showToastViewInCell:self toastText:[MQBundleUtil localizedStringForKey:@"save_photo_error"]];
}else{
// [self.chatCellDelegate showToastViewInCell:self toastText:[MQBundleUtil localizedStringForKey:@"save_photo_success"]];
}
}
+(CGFloat)tableHeightWithModel:(MessageModel *)model{
CGFloat masTop=10;
if (model.showMessageTime) {
masTop=37;
}
if (model.messageType==MessageTypeText) {
CGFloat maxWith=AppFrameWidth-LEFT_WITH-RIGHT_WITH-14-12-4;
UIFont *textFont=[UIFont fontWithName:FONT_REGULAR size:16];
NSDictionary *attributes = @{NSFontAttributeName: textFont};
CGRect rect = [model.messageText boundingRectWithSize:CGSizeMake(maxWith, MAXFLOAT)
options:NSStringDrawingUsesLineFragmentOrigin
attributes:attributes
context:nil];
return rect.size.height+26+masTop+20;
}else if (model.messageType==MessageTypeVoice){
return 40+masTop+20;
}else if (model.messageType==MessageTypeImage){
CGSize cgsize=[self imageShowSize:model.imageSmall];
return 40+cgsize.height+20;
}
return 0;
}
-(CGFloat)voiceLength:(NSInteger)seconds{ if (seconds==0) { return 75; } // 6~197 6p~230 // 75 CGFloat max=AppFrameWidth>750?230:197; return 75+(seconds-1)*(max-75)*1.0/60.0; }
/* 判断图片长度&宽度 */ +(CGSize)imageShowSize:(UIImage *)image{ CGFloat imageWith=image.size.width; CGFloat imageHeight=image.size.height; //宽度大于高度 if (imageWith>=imageHeight) { // 宽度超过标准宽度 /* if (imageWith>MAX_IMAGE_WH) { }else{ } */ return CGSizeMake(MAX_IMAGE_WH, imageHeight*MAX_IMAGE_WH/imageWith); }else{ /* if (imageHeight>MAX_IMAGE_WH) { }else{ } */ return CGSizeMake(imageWith*MAX_IMAGE_WH/imageHeight, MAX_IMAGE_WH); } return CGSizeZero; }-(void)startVoiceAnimation{
[self.voiceAnimationImageView startAnimating];
}
-(void)stopVoiceAnimation{
[self.voiceAnimationImageView stopAnimating];
}
-(void)startSentMessageAnimation{
}
-(void)stopSentMessageAnimation{
}
- (void)awakeFromNib {
[super awakeFromNib];
// Initialization code
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
@end
引用这个Cell 是比较容易的 。。
代码还是贴上吧。 。
定义的宏
#define RGBA(R,G,B,A) [UIColor colorWithRed:R/255.0 green:G/255.0 blue:B/255.0 alpha:A] #define RGB(R,G,B) [UIColor colorWithRed:R/255.0 green:G/255.0 blue:B/255.0 alpha:1.0] #define HEXRGB(rgbValue) [UIColor colorWithRed:((float)((rgbValue & 0xFF0000) >> 16))/255.0 green:((float)((rgbValue & 0xFF00) >> 8))/255.0 blue:((float)(rgbValue & 0xFF))/255.0 alpha:1.0] #define HEXRGBA(rgbValue,a) [UIColor colorWithRed:((float)((rgbValue & 0xFF0000) >> 16))/255.0 green:((float)((rgbValue & 0xFF00) >> 8))/255.0 blue:((float)(rgbValue & 0xFF))/255.0 alpha:a] #define AppFrameWidth [UIScreen mainScreen].bounds.size.width #define AppFrameHight [UIScreen mainScreen].bounds.size.height #define ISIOS7LATER ([[[UIDevice currentDevice] systemVersion] floatValue]>=7.0) #define ISIOS8LATER ([[[UIDevice currentDevice] systemVersion] floatValue]>=8.0) #define ISIOS9LATER ([[[UIDevice currentDevice] systemVersion] floatValue]>=9.0) #define ISIOS10LATER ([[[UIDevice currentDevice] systemVersion] floatValue]>=10.0) #define FONT_HEADTITLE [UIFont fontWithName:@"PingFangSC-Medium" size:24] #define NOTICE_LOGIN_SUC @"notice_login_suc" #define hiddenViewNotifaction @"hiddenViewNotifaction" #define loginViewShowNotifaction @"loginViewShowNotifaction" #define FONT_MEDIUM @"PingFangSC-Medium" #define FONT_REGULAR @"PingFangSC-Regular" #define FONT_SEMIBOLD @"PingFangSC-Semibold" #define FONT_SC @"PingFangSC" #define COLOR_ffffff HEXRGB(0xffffff) #define COLOR_f2f2f2 HEXRGB(0xf2f2f2) #define COLOR_f6f6f6 HEXRGB(0xf6f6f6) #define COLOR_a8a8a8 HEXRGB(0xa8a8a8) #define COLOR_444444 HEXRGB(0x444444) #define COLOR_f7f7f7 HEXRGB(0xf7f7f7) #define COLOR_e85b53 HEXRGB(0xe85b53) #define COLOR_666666 HEXRGB(0x666666) #define COLOR_bababa HEXRGB(0xbababa) #define COLOR_999999 HEXRGB(0x999999) #define COLOR_ececec HEXRGB(0xececec) #define COLOR_e6e6e6 HEXRGB(0xe6e6e6) #define COLOR_4ab495 HEXRGB(0x4ab495) #define COLOR_78879d HEXRGB(0x78879d) #define COLOR_313232 HEXRGB(0x313232) #define COLOR_abaaaa HEXRGB(0xabaaaa) #define COLOR_e3e3e3 HEXRGB(0xe3e3e3) #define COLOR_000000 HEXRGB(0x000000) #define COLOR_cecece HEXRGB(0xcecece) #define COLOR_2a9e39 HEXRGB(0x2a9e39) #define COLOR_c00000 HEXRGB(0xc00000)
然后是cell的调用
#import "ViewController.h" #import "ConstantPart.h" #import "WeChatCell.h" #import "MessageModel.h" @interface ViewController ()<UITableViewDelegate,UITableViewDataSource>{ UITableView *table; NSMutableArray<MessageModel *> *arrList; } @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. arrList=[[NSMutableArray alloc] init]; [self allocList]; table=[[UITableView alloc] initWithFrame:CGRectMake(0, 0, AppFrameWidth, AppFrameHight)]; table.separatorColor=[UIColor clearColor]; table.delegate=self; table.dataSource=self; [self.view addSubview:table]; } -(void)allocList{ MessageModel *model=[[MessageModel alloc] init]; model.showMessageTime=YES; model.messageTime=@"11:22"; model.messageText=@"中央军委主席习近平日前签署命令,追授海军某舰载航空兵部队一级飞行员张超“逐梦海天的强军先锋”荣誉称号。2016年4月27日,张超在驾驶歼-15进行陆基模拟着舰训练时,飞机突发电传故障,不幸壮烈牺牲。中央军委号召,全军和武警部队广大官兵要以张超同志为榜样,高举中国特色社会主义伟大旗帜,坚持以邓小平理论、“三个代表”重要思想、科学发展观为指导,深入学习贯彻习主席系列重要讲话精神,团结奋进,锐意创新,扎实工作,为实现强军目标、建设世界一流军队贡献智慧和力量"; model.messageSenderType=MessageSenderTypeHantu; model.messageType=MessageTypeText; [arrList addObject:model]; model=[[MessageModel alloc] init]; model.showMessageTime=NO; model.messageTime=@"11:22"; model.messageText=@"中央军委主席习近平日前签署命令,追授海军某舰载航空兵部队一级飞行员张超“逐梦海天的强军先锋”荣誉称号。2016年4月27日,张超在驾驶歼-15进行陆基模拟着舰训练时,飞机突发电传故障,不幸壮烈牺牲。中央军委号召,全军和武警部队广大官兵要以张超同志为榜样,高举中国特色社会主义伟大旗帜,坚持以邓小平理论、“三个代表”重要思想、科学发展观为指导,深入学习贯彻习主席系列重要讲话精神,团结奋进,锐意创新,扎实工作,为实现强军目标、建设世界一流军队贡献智慧和力量"; model.messageSenderType=MessageSenderTypeHantu; model.messageType=MessageTypeText; [arrList addObject:model]; model=[[MessageModel alloc] init]; model.showMessageTime=NO; model.messageTime=@"11:22"; model.messageText=@"中央军委主席"; model.messageSenderType=MessageSenderTypeHantu; model.messageType=MessageTypeText; [arrList addObject:model]; model=[[MessageModel alloc] init]; model.showMessageTime=NO; model.messageTime=@"11:22"; model.messageText=@"中央军委主席"; model.messageSenderType=MessageSenderTypeHantu; model.messageType=MessageTypeText; [arrList addObject:model]; model=[[MessageModel alloc] init]; model.showMessageTime=YES; model.messageTime=@"11:22"; model.messageText=@"中央军委主席习近平日前签署命令,追授海军某舰载航空兵部队一级飞行员张超“逐梦海天的强军先锋”荣誉称号。2016年4月27日,张超在驾驶歼-15进行陆基模拟着舰训练时,飞机突发电传故障,不幸壮烈牺牲。中央军委号召,全军和武警部队广大官兵要以张超同志为榜样,高举中国特色社会主义伟大旗帜,坚持以邓小平理论、“三个代表”重要思想、科学发展观为指导,深入学习贯彻习主席系列重要讲话精神,团结奋进,锐意创新,扎实工作,为实现强军目标、建设世界一流军队贡献智慧和力量"; model.messageSenderType=MessageSenderTypeUser; model.messageType=MessageTypeText; [arrList addObject:model]; model=[[MessageModel alloc] init]; model.showMessageTime=NO; model.messageTime=@"11:22"; model.messageText=@"中央军委主席习近平日前签署命令,追授海军某舰载航空兵部队一级飞行员张超“逐梦海天的强军先锋”荣誉称号。2016年4月27日,张超在驾驶歼-15进行陆基模拟着舰训练时,飞机突发电传故障,不幸壮烈牺牲。中央军委号召,全军和武警部队广大官兵要以张超同志为榜样,高举中国特色社会主义伟大旗帜,坚持以邓小平理论、“三个代表”重要思想、科学发展观为指导,深入学习贯彻习主席系列重要讲话精神,团结奋进,锐意创新,扎实工作,为实现强军目标、建设世界一流军队贡献智慧和力量中央军委主席习近平日前签署命令,追授海军某舰载航空兵部队一级飞行员张超“逐梦海天的强军先锋”荣誉称号。2016年4月27日,张超在驾驶歼-15进行陆基模拟着舰训练时,飞机突发电传故障,不幸壮烈牺牲。中央军委号召,全军和武警部队广大官兵要以张超同志为榜样,高举中国特色社会主义伟大旗帜,坚持以邓小平理论、“三个代表”重要思想、科学发展观为指导,深入学习贯彻习主席系列重要讲话精神,团结奋进,锐意创新,扎实工作,为实现强军目标、建设世界一流军队贡献智慧和力量中央军委主席习近平日前签署命令,追授海军某舰载航空兵部队一级飞行员张超“逐梦海天的强军先锋”荣誉称号。2016年4月27日,张超在驾驶歼-15进行陆基模拟着舰训练时,飞机突发电传故障,不幸壮烈牺牲。中央军委号召,全军和武警部队广大官兵要以张超同志为榜样,高举中国特色社会主义伟大旗帜,坚持以邓小平理论、“三个代表”重要思想、科学发展观为指导,深入学习贯彻习主席系列重要讲话精神,团结奋进,锐意创新,扎实工作,为实现强军目标、建设世界一流军队贡献智慧和力量中央军委主席习近平日前签署命令,追授海军某舰载航空兵部队一级飞行员张超“逐梦海天的强军先锋”荣誉称号。2016年4月27日,张超在驾驶歼-15进行陆基模拟着舰训练时,飞机突发电传故障,不幸壮烈牺牲。中央军委号召,全军和武警部队广大官兵要以张超同志为榜样,高举中国特色社会主义伟大旗帜,坚持以邓小平理论、“三个代表”重要思想、科学发展观为指导,深入学习贯彻习主席系列重要讲话精神,团结奋进,锐意创新,扎实工作,为实现强军目标、建设世界一流军队贡献智慧和力量中央军委主席习近平日前签署命令,追授海军某舰载航空兵部队一级飞行员张超“逐梦海天的强军先锋”荣誉称号。2016年4月27日,张超在驾驶歼-15进行陆基模拟着舰训练时,飞机突发电传故障,不幸壮烈牺牲。中央军委号召,全军和武警部队广大官兵要以张超同志为榜样,高举中国特色社会主义伟大旗帜,坚持以邓小平理论、“三个代表”重要思想、科学发展观为指导,深入学习贯彻习主席系列重要讲话精神,团结奋进,锐意创新,扎实工作,为实现强军目标、建设世界一流军队贡献智慧和力量中央军委主席习近平日前签署命令,追授海军某舰载航空兵部队一级飞行员张超“逐梦海天的强军先锋”荣誉称号。2016年4月27日,张超在驾驶歼-15进行陆基模拟着舰训练时,飞机突发电传故障,不幸壮烈牺牲。中央军委号召,全军和武警部队广大官兵要以张超同志为榜样,高举中国特色社会主义伟大旗帜,坚持以邓小平理论、“三个代表”重要思想、科学发展观为指导,深入学习贯彻习主席系列重要讲话精神,团结奋进,锐意创新,扎实工作,为实现强军目标、建设世界一流军队贡献智慧和力量中央军委主席习近平日前签署命令,追授海军某舰载航空兵部队一级飞行员张超“逐梦海天的强军先锋”荣誉称号。2016年4月27日,张超在驾驶歼-15进行陆基模拟着舰训练时,飞机突发电传故障,不幸壮烈牺牲。中央军委号召,全军和武警部队广大官兵要以张超同志为榜样,高举中国特色社会主义伟大旗帜,坚持以邓小平理论、“三个代表”重要思想、科学发展观为指导,深入学习贯彻习主席系列重要讲话精神,团结奋进,锐意创新,扎实工作,为实现强军目标、建设世界一流军队贡献智慧和力量"; model.messageSenderType=MessageSenderTypeUser; model.messageType=MessageTypeText; [arrList addObject:model]; model=[[MessageModel alloc] init]; model.showMessageTime=NO; model.messageTime=@"11:22"; model.messageText=@"中央军委主席习近平日"; model.messageSenderType=MessageSenderTypeUser; model.messageType=MessageTypeText; model.messageSentStatus=MessageSentStatusUnSended; [arrList addObject:model]; model=[[MessageModel alloc] init]; model.showMessageTime=NO; model.messageTime=@"11:22"; model.messageText=@"中央军委主席习近平日"; model.messageSenderType=MessageSenderTypeUser; model.messageType=MessageTypeText; model.messageSentStatus=MessageSentStatusUnSended; [arrList addObject:model]; model=[[MessageModel alloc] init]; model.showMessageTime=YES; model.messageTime=@"11:22"; model.messageText=@"中央军委主席习近平日"; model.messageSenderType=MessageSenderTypeUser; model.messageType=MessageTypeText; model.messageSentStatus=MessageSentStatusSended; model.messageReadStatus=MessageReadStatusRead; [arrList addObject:model]; model=[[MessageModel alloc] init]; model.showMessageTime=NO; model.messageTime=@"11:22"; model.messageText=@"中央军委"; model.messageSenderType=MessageSenderTypeUser; model.messageType=MessageTypeText; model.messageSentStatus=MessageSentStatusSended; model.messageReadStatus=MessageReadStatusUnRead; [arrList addObject:model]; model=[[MessageModel alloc] init]; model.showMessageTime=NO; model.messageTime=@"11:22"; model.messageText=@"中"; model.messageSenderType=MessageSenderTypeUser; model.messageType=MessageTypeText; [arrList addObject:model]; model=[[MessageModel alloc] init]; model.showMessageTime=NO; model.messageTime=@"11:22"; model.duringTime=55; model.messageSenderType=MessageSenderTypeUser; model.messageType=MessageTypeVoice; [arrList addObject:model]; model=[[MessageModel alloc] init]; model.showMessageTime=NO; model.messageTime=@"11:22"; model.duringTime=55; model.messageSenderType=MessageSenderTypeUser; model.messageType=MessageTypeVoice; [arrList addObject:model]; model=[[MessageModel alloc] init]; model.showMessageTime=YES; model.messageTime=@"11:22"; model.duringTime=4; model.messageSenderType=MessageSenderTypeUser; model.messageType=MessageTypeVoice; [arrList addObject:model]; model=[[MessageModel alloc] init]; model.showMessageTime=NO; model.messageTime=@"11:22"; model.duringTime=9; model.messageSentStatus=MessageSentStatusSending; model.messageReadStatus=MessageReadStatusUnRead; model.messageSenderType=MessageSenderTypeUser; model.messageType=MessageTypeVoice; [arrList addObject:model]; model=[[MessageModel alloc] init]; model.showMessageTime=NO; model.messageTime=@"11:22"; model.duringTime=9; model.messageSentStatus=MessageSentStatusUnSended; // model.messageReadStatus=MessageReadStatusUnRead; model.messageSenderType=MessageSenderTypeUser; model.messageType=MessageTypeVoice; [arrList addObject:model]; model=[[MessageModel alloc] init]; model.showMessageTime=NO; model.messageTime=@"11:22"; model.duringTime=9; model.messageSentStatus=MessageSentStatusSended; model.messageReadStatus=MessageReadStatusUnRead; model.messageSenderType=MessageSenderTypeUser; model.messageType=MessageTypeVoice; [arrList addObject:model]; model=[[MessageModel alloc] init]; model.showMessageTime=NO; model.messageTime=@"11:22"; model.duringTime=9; model.messageSentStatus=MessageSentStatusSended; model.messageReadStatus=MessageReadStatusRead; model.messageSenderType=MessageSenderTypeUser; model.messageType=MessageTypeVoice; [arrList addObject:model]; model=[[MessageModel alloc] init]; model.showMessageTime=YES; model.messageTime=@"11:22"; model.duringTime=9; model.messageSenderType=MessageSenderTypeHantu; model.messageType=MessageTypeVoice; [arrList addObject:model]; model=[[MessageModel alloc] init]; model.showMessageTime=YES; model.messageTime=@"11:22"; model.duringTime=9; model.messageSenderType=MessageSenderTypeHantu; model.messageType=MessageTypeImage; model.imageSmall=[UIImage imageNamed:@"WechatIMG4e"]; [arrList addObject:model]; model=[[MessageModel alloc] init]; model.showMessageTime=YES; model.messageTime=@"11:22"; model.duringTime=9; model.messageSenderType=MessageSenderTypeUser; model.messageType=MessageTypeImage; model.messageSentStatus=MessageSentStatusSended; model.messageReadStatus=MessageReadStatusRead; model.imageSmall=[UIImage imageNamed:@"WechatIMG4e"]; [arrList addObject:model]; model=[[MessageModel alloc] init]; model.showMessageTime=YES; model.messageTime=@"11:22"; model.duringTime=9; model.messageSenderType=MessageSenderTypeUser; model.messageType=MessageTypeImage; model.messageSentStatus=MessageSentStatusSended; model.messageReadStatus=MessageReadStatusUnRead; model.imageSmall=[UIImage imageNamed:@"WechatIMG4e"]; [arrList addObject:model]; model=[[MessageModel alloc] init]; model.showMessageTime=YES; model.messageTime=@"11:22"; model.duringTime=9; model.messageSenderType=MessageSenderTypeUser; model.messageType=MessageTypeImage; model.messageSentStatus=MessageSentStatusSending; model.messageReadStatus=MessageReadStatusRead; model.imageSmall=[UIImage imageNamed:@"WechatIMG4e"]; [arrList addObject:model]; model=[[MessageModel alloc] init]; model.showMessageTime=YES; model.messageTime=@"11:22"; model.duringTime=9; model.messageSenderType=MessageSenderTypeUser; model.messageType=MessageTypeImage; model.messageSentStatus=MessageSentStatusUnSended; model.messageReadStatus=MessageReadStatusRead; model.imageSmall=[UIImage imageNamed:@"WechatIMG4e"]; [arrList addObject:model]; } -(void)scrollViewDidScroll:(UIScrollView *)scrollView{ // [[NSNotificationCenter defaultCenter] postNotificationName:@"notice_hidden" object:nil]; [[UIMenuController sharedMenuController] setMenuVisible:NO animated:YES]; } -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{ return [arrList count]; } -(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{ return 1; } -(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{ return [WeChatCell tableHeightWithModel:arrList[indexPath.row]]; } -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ WeChatCell *cell=[WeChatCell cellWithTableView:table messageModel:arrList[indexPath.row]]; [cell setDoubleClickBlock:^(MessageModel *model) { NSLog(@"%@-----",model.messageText); }]; [cell setSingleblock:^(MessageModel *model) { // NSLog(@"%@-----",model.imageUrl); if (model.messageType==MessageTypeVoice) { }else if (model.messageType==MessageTypeImage){ } }]; [cell setResendblock:^(MessageModel *model) { }]; return cell; } -(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{ } /* -(void)aaa:(id)sender { } -(BOOL)canBecomeFirstResponder{ return YES; } -(BOOL)canPerformAction:(SEL)action withSender:(id)sender{ return YES; } */ - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } @end
调用很简单。。。 如果你不明白还是 上github下载下来搞一搞
https://github.com/hebiao6446/HeBiaoWeChat
相关文章推荐
- IOS高访微信聊天对话界面(sizeWithFont:constrainedToSize和stretchableImageWithLeftCapWidth的使用)
- iOS微信QQ聊天界面的UI框架以及Socket简单实现群聊功能
- 【iOS基础控件 - 11】【Demo】模仿qq ,微信 UI 聊天界面
- IOS高访微信聊天对话界面(sizeWithFont:constrainedToSize和stretchableImageWithLeftCapWidth的使用)
- IOS高访微信聊天对话界面(sizeWithFont:constrainedToSize和stretchableImageWithLeftCapWidth的使用)
- IOS高访微信聊天对话界面(sizeWithFont:constrainedToSize和stretchableImageWithLeftCapWidth的使用)
- IOS高访微信聊天对话界面(sizeWithFont:constrainedToSize和stretchableImageWithLeftCapWidth的使用)
- iOS 类似微信,QQ聊天界面的气泡聊天简单实现Demo
- ios开发仿写微信视频聊天界面
- IOS高访微信聊天对话界面(sizeWithFont:constrainedToSize和stretchableImageWithLeftCapWidth的使用)
- iOS微信聊天界面朋友圈多个小视频同时播放不卡顿
- ios 实现微信的非最近会话聊天界面的返回按钮
- IOS高访微信聊天对话界面(sizeWithFont:constrainedToSize和stretchableImageWithLeftCapWidth的使用)
- IOS高访微信聊天对话界面(sizeWithFont:constrainedToSize和stretchableImageWithLeftCapWidth的使用)
- IOS高访微信聊天对话界面(sizeWithFont:constrainedToSize和stretchableImageWithLeftCapWidth的使用)
- iOS_29仿微信聊天界面
- Lance老师UI系列教程第六课->微信聊天气泡界面的实现
- ios 仿微信,短信聊天气泡
- Android仿微信气泡聊天界面设计
- 类似微信的聊天界面ListView