环信3.x自定义表情实现https://www.tuicool.com/articles/YVrmY33
很久没有写了,首先给张效果图,有自定义的cell,有cell的点击事件,有自定义的chatBarMoreView:
推荐的做法
//先注册
[self.tableView registerNib:[UINib nibWithNibName:@"ClubRoomChatNoticeCell" bundle:nil] forCellReuseIdentifier:@"ClubRoomChatNoticeCell"];
- (UITableViewCell *)messageViewController:(UITableView *)tableView cellForMessageModel:(id)model
{
if ([[model.message.ext objectForKey:@"type"] isEqualToString:@"announced"]) {
ClubChatOpenPrizeCell *cell = (ClubChatOpenPrizeCell *)[tableView dequeueReusableCellWithIdentifier:@"ClubChatOpenPrizeCell"];
cell.title.text = [NSString stringWithFormat:@"%@",model.text];
return cell;
}
return nil;
}
以下这种做法不推荐
我的思路是直接修改源码的(如果不修改源码能实现最好)大家可以借鉴处理的过程及思路,如有不妥之处,请大家及时留言告知
环信初始化
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
EMOptions *options = [EMOptions optionsWithAppkey:@"Xxxxxx"];
options.enableConsoleLog = NO;
[[EMClient sharedClient] initializeSDKWithOptions:options];
//监听自动登录的状态
[[EMClient sharedClient] addDelegate:self delegateQueue:nil];
[[EMClient sharedClient].chatManager addDelegate:self delegateQueue:nil];
return YES;
}
- (void)didConnectionStateChanged:(EMConnectionState)aConnectionState{
if (aConnectionState == EMConnectionConnected) {
NSLog(@"网络连接成功");
}else{
NSLog(@"网络断开");
//监听网络状态(这里通知的目地是检测到如果没网络的情况下,修改Navigation.title的值)
}
}
- (void)connectionStateDidChange:(EMConnectionState)aConnectionState{
NSLog(@"断线重连不需要其他操作%u",aConnectionState);
}
- (void)userAccountDidLoginFromOtherDevice{
NSLog(@"在别的设备上登陆了");
}
- (void)autoLoginDidCompleteWithError:(EMError *)aError{
NSLog(@"自动登录完成时的回调");
}
- (void)messagesDidReceive:(NSArray *)aMessages{
NSLog(@"收到一条新的消息");
for (EMMessage *message in aMessages) {
NSLog(@"%@",message);
}
}
创建单聊页面,主要是发送扩展消息,
//
// SingleChatViewController.m
// TextChat
//
// Created by apple on 2017/10/18.
// Copyright © 2017年 刘龙飞. All rights reserved.
//
#import "SingleChatViewController.h"
@interface SingleChatViewController ()
@end
@implementation SingleChatViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
self.delegate = self;
self.dataSource = self;
self.chatBarMoreView.delegate = self;
self.showRefreshHeader = YES;
//去掉多余的按钮
[self.chatBarMoreView removeItematIndex:0];
[self.chatBarMoreView removeItematIndex:0];
[self.chatBarMoreView removeItematIndex:0];
[self.chatBarMoreView removeItematIndex:0];
[self.chatBarMoreView removeItematIndex:0];
//自定义按钮
[self.chatBarMoreView insertItemWithImage:[UIImage imageNamed:@"wwww"] highlightedImage:[UIImage imageNamed:@"wwwwl"] title:@"就"];
[self.chatBarMoreView insertItemWithImage:[UIImage imageNamed:@"wwww"] highlightedImage:[UIImage imageNamed:@"wwww"] title:@"这样"];
[self.chatBarMoreView insertItemWithImage:[UIImage imageNamed:@"wwww"] highlightedImage:[UIImage imageNamed:@"wwww"] title:@"被你"];
[self.chatBarMoreView insertItemWithImage:[UIImage imageNamed:@"wwww"] highlightedImage:[UIImage imageNamed:@"wwww"] title:@"征服"];
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:(UIBarButtonSystemItemAdd) target:self action:@selector(touchRightButton)];
}
#pragma mark - EaseChatBarMoreViewDelegate
- (void)moreView:(EaseChatBarMoreView *)moreView didItemInMoreViewAtIndex:(NSInteger)index{
NSLog(@"点击自定义按钮----%ld",(long)index);
}
#pragma mark - EaseMessageViewControllerDataSource
///消息显示用户昵称和头像。
//- (id)messageViewController:(EaseMessageViewController *)viewController
// modelForMessage:(EMMessage *)message{
// id model = nil;
// model = [[EaseMessageModel alloc] initWithMessage:message];
// model.avatarImage = [UIImage imageNamed:@"EaseUIResource.bundle/user"];//默认头像
// model.nickname = @"";//用户昵称
// if (message.direction == EMMessageDirectionSend) {
// NSString *headImg = [NSString stringWithFormat:@"%@%@",FILE_PATH,[ToolsManager loginUser].headImage];
// model.avatarURLPath = headImg;
// }
// else if (message.direction == EMMessageDirectionReceive) {
// NSString *headImg = [NSString stringWithFormat:@"%@%@",FILE_PATH,_relatives.imagePath];
// model.avatarURLPath = headImg;
// }
// return model;
//}
#pragma mark - EaseMessageViewControllerDelegate
- (UITableViewCell *)messageViewController:(UITableView *)tableView cellForMessageModel:(id)model
{
if ([model.message.ext objectForKey:@"msgtype"]) {
NSString *CellIdentifier = [EaseMessageCell cellIdentifierWithModel:model];
EaseMessageCell *cell = (EaseMessageCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[EaseMessageCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier model:model];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
cell.model = model;
cell.delegate = self;
}
return nil;
}
- (CGFloat)messageViewController:(EaseMessageViewController *)viewController
heightForMessageModel:(id)messageModel
withCellWidth:(CGFloat)cellWidth
{
if ([messageModel.message.ext objectForKey:@"msgtype"]) {
return 110;
}
return 0.f;
}
-(void)messageCellSelected:(id)model{
if ([model.message.ext objectForKey:@"msgtype"]) {
NSLog(@"------你点了自定义cell------");
}
}
//长按收拾回调样例:
- (BOOL)messageViewController:(EaseMessageViewController *)viewController
canLongPressRowAtIndexPath:(NSIndexPath *)indexPath
{
//样例给出的逻辑是所有cell都允许长按
return YES;
}
- (void)messagesDidRead:(NSArray *)aMessages{
NSLog(@"已读回执");
}
#pragma mark - Private
-(void)touchRightButton{
NSDictionary *messageExt = @{
@"msgtype":@"025",
@"userId":@"chenchenchenchen",
@"userHeadImg":@"sisisisi",
@"userName":@"yanyanyanyanyan我是自定义的cell"
};
[self sendTextMessage:@"我可以永远笑着扮演你的配角 在你的背后自己煎熬 如果你不想要 想退出要趁早" withExt:messageExt];
}
@end
仿照环信的cell写一个EaseBubbleView的分类
import "EaseBubbleView.h"
@interface EaseBubbleView (TopicText)
/*!
@method
@brief 构建文本类型消息气泡视图
@discussion
@result
*/
- (void)setupTextBubbleViewTopic;
/*!
@method
@brief 变更文本类型消息气泡的边距,并更新改子视图约束
@discussion
@param margin 气泡边距
@result
*/
- (void)updateTextMarginTopic:(UIEdgeInsets)margin;
@end
#import "EaseBubbleView+Text.h"
@implementation EaseBubbleView (Text)
#pragma mark - private
- (void)_setupTextBubbleMarginConstraintsTopic
{
NSLayoutConstraint *marginTopConstraint = [NSLayoutConstraint constraintWithItem:self.textLabel attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.backgroundImageView attribute:NSLayoutAttributeTop multiplier:1.0 constant:self.margin.top];
NSLayoutConstraint *marginLeftConstraint = [NSLayoutConstraint constraintWithItem:self.textLabel attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:self.backgroundImageView attribute:NSLayoutAttributeRight multiplier:1.0 constant:-self.margin.right];
NSLayoutConstraint *marginRightConstraint = [NSLayoutConstraint constraintWithItem:self.textLabel attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self.backgroundImageView attribute:NSLayoutAttributeLeft multiplier:1.0 constant:self.margin.left];
NSLayoutConstraint *marginRightConstraintHeight = [NSLayoutConstraint constraintWithItem:self.textLabel attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:self.backgroundImageView attribute:NSLayoutAttributeHeight multiplier:0.5 constant:0];
[self.marginConstraints removeAllObjects];
[self.marginConstraints addObject:marginTopConstraint];
[self.marginConstraints addObject:marginLeftConstraint];
[self.marginConstraints addObject:marginRightConstraint];
[self.marginConstraints addObject:marginRightConstraintHeight];
[self addConstraints:self.marginConstraints];
}
- (void)_setupTextBubbleConstraintsTopic
{
[self _setupTextBubbleMarginConstraintsTopic];
//增加新控件约束
[self addConstraint:[NSLayoutConstraint constraintWithItem:self.myTextLabel attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self.backgroundImageView attribute:NSLayoutAttributeBottom multiplier:1.0 constant:-10]];
[self addConstraint:[NSLayoutConstraint constraintWithItem:self.myTextLabel attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:self.textLabel attribute:NSLayoutAttributeRight multiplier:1.0 constant:-self.margin.right]];
[self addConstraint:[NSLayoutConstraint constraintWithItem:self.myTextLabel attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self.textLabel attribute:NSLayoutAttributeLeft multiplier:1.0 constant:self.margin.left]];
[self addConstraint:[NSLayoutConstraint constraintWithItem:self.myTextLabel attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:self.backgroundImageView attribute:NSLayoutAttributeHeight multiplier:0.3 constant:0]];
}
#pragma mark - public
- (void)setupTextBubbleViewTopic
{
self.textLabel = [[UILabel alloc] init];
self.textLabel.translatesAutoresizingMaskIntoConstraints = NO;
self.textLabel.backgroundColor = [UIColor clearColor];
self.textLabel.numberOfLines = 2;
[self.backgroundImageView addSubview:self.textLabel];
// 新的UI控件
self.myTextLabel = [[UILabel alloc]init];
self.myTextLabel.font = [UIFont systemFontOfSize:12];
self.myTextLabel.backgroundColor = [UIColor orangeColor];
self.myTextLabel.translatesAutoresizingMaskIntoConstraints = NO;
[self.backgroundImageView addSubview:self.myTextLabel];
[self _setupTextBubbleConstraintsTopic];
}
- (void)updateTextMarginTopic:(UIEdgeInsets)margin
{
if (_margin.top == margin.top && _margin.bottom == margin.bottom && _margin.left == margin.left && _margin.right == margin.right) {
return;
}
_margin = margin;
[self removeConstraints:self.marginConstraints];
[self _setupTextBubbleMarginConstraintsTopic];
}
@end
然后在EaseMessageCell里仿写环信的cell,判断是不是扩展消息,
//渲染
case EMMessageBodyTypeText:
{
if ([model.message.ext objectForKey:@"msgtype"]) {
[_bubbleView setupTextBubbleViewTopic];
_bubbleView.textLabel.font = _messageTextFont;
_bubbleView.textLabel.textColor = _messageTextColor;
}else{
[_bubbleView setupTextBubbleView];
_bubbleView.textLabel.font = _messageTextFont;
_bubbleView.textLabel.textColor = _messageTextColor;
}
}
break;
//数据模型
case EMMessageBodyTypeText:
{
if ([self.model.message.ext objectForKey:@"msgtype"]) {
_bubbleView.textLabel.attributedText = [[EaseEmotionEscape sharedInstance] attStringFromTextForChatting:model.text textFont:self.messageTextFont];
_bubbleView.myTextLabel.text = [self.model.message.ext objectForKey:@"userName"];
}else{
_bubbleView.textLabel.attributedText = [[EaseEmotionEscape sharedInstance] attStringFromTextForChatting:model.text textFont:self.messageTextFont];
}
}
break;
//跟新约束
case EMMessageBodyTypeText:
{
if ([self.model.message.ext objectForKey:@"msgtype"]) {
[_bubbleView updateTextMarginTopic:_bubbleMargin];
}else{
[_bubbleView updateTextMargin:_bubbleMargin];
}
}
break;
//cell的点击事件
case EMMessageBodyTypeText:
{
if ([_delegate respondsToSelector:@selector(messageCellSelected:)]) {
[_delegate messageCellSelected:_model];
}
}
break;
//获取cell的重用标识
case EMMessageBodyTypeText:
if ([model.message.ext objectForKey:@"msgtype"]) {
cellIdentifier = EaseMessageCellIdentifierSendTextTTopic;
}else{
cellIdentifier = EaseMessageCellIdentifierSendText;
}
break;
case EMMessageBodyTypeText:
if ([model.message.ext objectForKey:@"msgtype"]) {
cellIdentifier = EaseMessageCellIdentifierRecvTextTTopic;
}else{
cellIdentifier = EaseMessageCellIdentifierRecvText;
}
break;