Skip to content

Latest commit

 

History

History
826 lines (681 loc) · 26.8 KB

README.md

File metadata and controls

826 lines (681 loc) · 26.8 KB

说明:

  • 本Demo使用的是 版本号为2.2.6环信官方Demo
  • 下载Demo后解压根目录下的EaseMobSDK.zip
  • 将appDelegate中[[MMEmotionCentre defaultCentre] setAppId:@“your app id” secret:@“your secret”]设置成分配到的idsecret
  • 本Demo在环信官方Demo的基础上集成了BQMM1.7,在修改的地方我们都加上了“BQMM集成"的注释,可在项目中全局搜索查看。
  • 我们提供了集成之后的Demo与官方Demo的Diff文档ChatDemo2.2.6_BQMM集成文档.html,供大家查看。

表情云SDK接入文档

接入SDK,有以下必要步骤:

  1. 下载与安装
  2. 获取必要的接入信息
  3. 开始集成

##第一步:下载与安装

目前有两种方式安装SDK:

  • 通过CocoaPods管理依赖。
  • 手动导入SDK并管理依赖。

###1. 使用 CocoaPods 导入SDK

在终端中运行以下命令:

pod search BQMM

如果运行以上命令,没有搜到SDK,或者搜不到最新的 SDK 版本,您可以运行以下命令,更新您本地的 CocoaPods 源列表。

pod repo update

在您工程的 Podfile中添加最新版本的SDK(在此以2.1版本为例):

pod 'BQMM', '2.1'

然后在工程的根目录下运行以下命令:

pod install

说明:pod中不包含gif表情的UI模块,可在官网下载,手动导入BQMM_GIF

###2. 手动导入SDK

下载当前最新版本,解压缩后获得3个文件夹

  • BQMM
  • BQMM_EXT
  • BQMM_GIF

BQMM中包含SDK所需的资源文件BQMM.bundle和库文件BQMM.framework;BQMM_EXT提供了SDK的默认消息显示控件和消息默认格式的开源代码,开发者们导入后可按需修改;BQMM_GIF中包含gif表情的UI模块,开发者导入后可按需修改。

###3. 添加系统库依赖

您除了在工程中导入 SDK 之外,还需要添加libz动态链接库。

##第二步:获取必要的接入信息

开发者将应用与SDK进行对接时,必要接入信息如下

  • appId - 应用的App ID
  • appSecret - 应用的App Secret

如您暂未获得以上接入信息,可以在此申请

##第三步:开始集成

###0. 注册AppId&AppSecret、设置SDK语言和区域

AppDelegate-application:didFinishLaunchingWithOptions: 中添加:

// 初始化SDK
[[MMEmotionCentre defaultCentre] setAppId:@“your app idsecret:@“your secret”]

//设置SDK语言和区域
[MMEmotionCentre defaultCentre].sdkLanguage = MMLanguageEnglish;
[MMEmotionCentre defaultCentre].sdkRegion = MMRegionChina;

###1. 在App重新打开时清空session

AppDelegate- (void)applicationWillEnterForeground: 中添加:

[[MMEmotionCentre defaultCentre] clearSession];

###2. 使用表情键盘和GIF搜索模块

####设置SDK代理

EaseChatToolbar.m

- (instancetype)initWithFrame:(CGRect)frame {
    ....
    //BQMM集成
    [MMEmotionCentre defaultCentre].delegate = self;
    ....
}

####配置GIF搜索模块

EaseMessageViewController.m

- (void)viewDidLoad {
    ....
    //BQMM集成   设置gif搜索相关
    [[MMGifManager defaultManager] setSearchModeEnabled:true withInputView:_inputToolBar.inputTextView];
    [[MMGifManager defaultManager] setSearchUiVisible:true withAttatchedView:_inputToolBar];
        
    __weak typeof(self) weakSelf = self;
    [MMGifManager defaultManager].selectedHandler = ^(MMGif * _Nullable gif) {
        __strong MMChatViewController *strongSelf = weakSelf;
        if (strongSelf) {
            [strongSelf didSendGifMessage:gif];
        }
    };
    ....
}

-(void)didSendGifMessage:(MMGif *)gif {
    NSString *sendStr = [@"[" stringByAppendingFormat:@"%@]", gif.text];
    NSDictionary *msgData = @{@"sticker_url": gif.mainImage, @"is_gif": (gif.isAnimated ? @"1" : @"0"), @"data_id": gif.imageId,@"w": @((float)gif.size.width), @"h": @((float)gif.size.height)};
    NSDictionary *extDic = @{@"txt_msgType":@"webtype",
                             @"msg_data":msgData
                             };
    EMMessage *message = [EaseSDKHelper sendTextMessage:sendStr
                                                     to:self.conversation.chatter
                                            messageType:[self _messageTypeFromConversationType]
                                      requireEncryption:NO
                                             messageExt:extDic];
    [self addMessageToDataSource:message
                        progress:nil];
    
}

####实现SDK代理方法

EaseChatToolbar.m 实现了SDK的代理方法

//点击键盘中大表情的代理
- (void)didSelectEmoji:(MMEmoji *)emoji
{
    if ([self.delegate respondsToSelector:@selector(didSendMMFace:)]) {
        [self.delegate didSendMMFace:emoji];
    }
}

//点击联想表情的代理 (`deprecated`)
- (void)didSelectTipEmoji:(MMEmoji *)emoji
{
    if ([self.delegate respondsToSelector:@selector(didSendMMFace:)]) {
        [self.delegate didSendMMFace:emoji];
        self.inputTextView.text = @"";
    }
}

//点击小表情键盘上发送按钮的代理
- (void)didSendWithInput:(UIResponder<UITextInput> *)input
{
    if ([input isKindOfClass:[UITextView class]]) {
        UITextView *textView = (UITextView *)input;
        NSString *sendStr = textView.characterMMText;
        sendStr = [sendStr stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
        if (![sendStr isEqualToString:@""]) {
            if ([self.delegate respondsToSelector:@selector(didSendTextMessageWithTextView:)]) {
                [self.delegate didSendTextMessageWithTextView:textView];
                self.inputTextView.text = @"";
                [self _willShowInputTextViewToHeight:[self _getTextViewContentH:_inputTextView]];
            }
        }
    }
}

//点击输入框切换表情按钮状态
- (void)tapOverlay
{
    self.faceButton.selected = NO;
}

//点击gifTab
- (void)didClickGifTab {
    self.faceButton.selected = NO;
    if ([self.delegate respondsToSelector:@selector(didClickGifTab)]) {
        [self.delegate didClickGifTab];
    }
}

EaseChatToolbar 通过代理将发送大表情及点击gif按钮代理给EaseMessageViewController

//BQMM集成

/**
 *  点击Gif tab
 */
- (void)didClickGifTab;

/**
 *  发送表情MM大表情
 *
 *  @param emoji 表情对象
 */
- (void)didSendMMFace:(MMEmoji *)emoji;

/**
 *  发送表情MM大表情
 *
 *  @param emoji 表情对象
 *  @param ext 扩展消息
 */
- (void)didSendMMFace:(MMEmoji *)emoji withExt:(NSDictionary*)ext;

EaseMessageViewController

//点击键盘中的gif按钮
- (void)didClickGifTab {
    //点击gif tab 后应该保证搜索模式是打开的 搜索UI是允许显示的
    [[MMGifManager defaultManager] setSearchModeEnabled:true withInputView:((EaseChatToolbar *)self.chatToolbar).inputTextView];
    [[MMGifManager defaultManager] setSearchUiVisible:true withAttatchedView:self.chatToolbar];
    [[MMGifManager defaultManager] showTrending];
}

####表情键盘和普通键盘的切换

EaseChatToolbar

- (void)faceButtonAction:(id)sender
{
    ...
    //替换成表情MM键盘
    if (button.selected) {
        self.moreButton.selected = NO;
        [[MMEmotionCentre defaultCentre] attachEmotionKeyboardToInput:_inputTextView];
        if (!_inputTextView.isFirstResponder) {
            [_inputTextView becomeFirstResponder];
        }
        self.faceButton.selected = YES;
    }
    else {
        //切换成普通键盘
        [[MMEmotionCentre defaultCentre] switchToDefaultKeyboard];
    }
}

###3. 使用表情消息编辑控件 SDK提供UITextView+BQMM作为表情编辑控件的扩展实现,可以以图文混排方式编辑,并提取编辑内容。 消息编辑框需要使用此控件,在适当位置引入头文件

#import <BQMM/BQMM.h>

###4.消息的编码及发送

表情相关的消息需要编码成extData放入IM的普通文字消息的扩展字段,发送到接收方进行解析。 extData是SDK推荐的用于解析的表情消息发送格式,格式是一个二维数组,内容为拆分完成的textemojiCode,并且说明这段内容是否是一个emojiCode

#####图文混排消息 EaseChatToolbar

- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
{
    if ([text isEqualToString:@"\n"]) {
        if ([self.delegate respondsToSelector:@selector(didSendText:)]) {
            //BQMM集成
            NSString *sendStr = self.inputTextView.characterMMText;
            sendStr = [sendStr stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
            if (![sendStr isEqualToString:@""]) {
                if ([self.delegate respondsToSelector:@selector(didSendTextMessageWithTextView:)]) {
                    [self.delegate didSendTextMessageWithTextView:self.inputTextView];
                }
            }

            self.inputTextView.text = @"";
            [self _willShowInputTextViewToHeight:[self _getTextViewContentH:self.inputTextView]];
        }
        
        return NO;
    }
    ...
}

EaseMessageViewController

- (void)didSendTextMessageWithTextView:(UITextView *)textView {
    NSString *sendStr = textView.characterMMText;
    NSMutableDictionary *ext = [NSMutableDictionary dictionary];
    NSArray *textImgArray = textView.textImgArray;
    NSDictionary *mmExt = @{@"txt_msgType":@"emojitype",
                            @"msg_data":[MMTextParser extDataWithTextImageArray:textImgArray]};;
    [ext addEntriesFromDictionary:mmExt];
    [self sendTextMessage:sendStr withExt:mmExt];
}

#####大表情消息

EaseMessageViewController

-(void)sendMMFaceMessage:(MMEmoji *)emoji
{
    NSDictionary *mmExt = @{@"txt_msgType":@"facetype",
                            @"msg_data":[MMTextParser extDataWithEmoji:emoji]};
    [self sendMMFaceMessage:emoji withExt:mmExt];
}

#####Gif表情消息

EaseMessageViewController

-(void)didSendGifMessage:(MMGif *)gif {
    NSString *sendStr = [@"[" stringByAppendingFormat:@"%@]", gif.text];
    NSDictionary *msgData = @{@"sticker_url": gif.mainImage, @"is_gif": (gif.isAnimated ? @"1" : @"0"), @"data_id": gif.imageId,@"w": @((float)gif.size.width), @"h": @((float)gif.size.height)};
    NSDictionary *extDic = @{@"txt_msgType":@"webtype",
                             @"msg_data":msgData
                             };
    EMMessage *message = [EaseSDKHelper sendTextMessage:sendStr
                                                     to:self.conversation.chatter
                                            messageType:[self _messageTypeFromConversationType]
                                      requireEncryption:NO
                                             messageExt:extDic];
    [self addMessageToDataSource:message
                        progress:nil];
    
}

Gif表情消息扩展解析出的图片尺寸存储在gifSize中,用于显示时布局。 EaseMessageModelIMessageModel

@property (nonatomic) CGSize gifSize;

###5. 表情消息的解析

消息的扩展解析 EaseMessageModelIMessageModel

//存储消息的扩展
@property (strong, nonatomic) NSDictionary *mmExt;
@property (nonatomic) CGSize gifSize;

EaseMessageModel

- (instancetype)initWithMessage:(EMMessage *)message
{
    self = [super init];
    if (self) {
        ...
        //BQMM集成
        NSDictionary *ext = message.ext;
        self.mmExt = ext;
        CGSize size = CGSizeZero;
        if([ext[TEXT_MESG_TYPE] isEqualToString: TEXT_MESG_WEB_TYPE]) {
            NSDictionary *msgData = ext[TEXT_MESG_DATA];
            float height = [msgData[WEBSTICKER_HEIGHT] floatValue];
            float width = [msgData[WEBSTICKER_WIDTH] floatValue];
            //宽最大200 高最大 150
            if (width > 200) {
                height = 200.0 / width * height;
                width = 200;
            }else if(height > 150) {
                width = 150.0 / height * width;
                height = 150;
            }
            size = CGSizeMake(width, height);
        }
        self.gifSize = size;
    }
}

混排消息的解析

从消息的扩展中解析出extData

NSDictionary *extDic = messageModel.ext;
if (extDic != nil && [extDic[@"txt_msgType"] isEqualToString:@"emojitype"]) {
    NSArray *extData = extDic[@"msg_data"];
}

单个大表情解析

从消息的扩展中解析出大表情(MMEmoji)的emojiCode

CustomMessageCell

- (void)setCustomModel:(id<IMessageModel>)model
{
	...
	else if ([model.mmExt[TEXT_MESG_TYPE] isEqualToString:TEXT_MESG_FACE_TYPE]) {
		...
		NSString *emojiCode = nil;
        if (model.mmExt[TEXT_MESG_DATA]) {
            emojiCode = model.mmExt[TEXT_MESG_DATA][0][0];
        }
        ...
	}
	...
}

Gif表情解析

从消息的扩展中解析出Gif表情(MMGif)的imageId和mainImage

CustomMessageCell

- (void)setCustomModel:(id<IMessageModel>)model
{
	...
	else if ([model.mmExt[TEXT_MESG_TYPE] isEqualToString:TEXT_MESG_WEB_TYPE]) {
		...
		NSDictionary *msgData = model.mmExt[TEXT_MESG_DATA];
        NSString *webStickerUrl = msgData[WEBSTICKER_URL];
        NSString *webStickerId = msgData[WEBSTICKER_ID];
        ...
	}
	...
}

###6. 表情消息显示

混排消息

SDK提供MMTextView作为显示图文混排表情消息的展示, Demo中添加了EMBubbleView+MMText扩展便于布局。 初始化: EMBubbleView+MMText

- (void)setupMMTextBubbleViewWithModel:(id<IMessageModel>)model
{
    ...
    self.textView = [[MMTextView alloc] init];
    self.textView.mmFont = [UIFont systemFontOfSize:15];
    self.textView.mmTextColor = [UIColor blackColor];
    ...
}  

设置数据: CustomMessageCell

- (void)setCustomModel:(id<IMessageModel>)model
{
    if ([model.mmExt[TEXT_MESG_TYPE] isEqualToString:TEXT_MESG_EMOJI_TYPE]) {
        [_bubbleView.textView setMmTextData:model.mmExt[TEXT_MESG_DATA]];
    }
    ...
}

复制消息内容: EaseMessageViewController

- (void)copyMenuAction:(id)sender
{
    //BQMM集成
    UIPasteboard *pasteboard = [UIPasteboard generalPasteboard];
    if (self.menuIndexPath && self.menuIndexPath.row > 0) {
        id<IMessageModel> model = [self.dataArray objectAtIndex:self.menuIndexPath.row];
        if ([model.mmExt[@"txt_msgType"] isEqualToString:@"emojitype"]) {
            pasteboard.string = [MMTextParser stringWithExtData:model.mmExt[@"msg_data"]];
        }
        else {
            pasteboard.string = model.text;
        }
    }
    
    self.menuIndexPath = nil;
}

另外,开发者可参照MMTextView中的updateAttributeTextWithData:completionHandler:方法定义自己的表情消息显示方式。参数extData是拆分过的文本和emojiCode

大表情消息 && gif表情消息

SDK 提供 MMImageView 来显示单个大表情及gif表情

EaseBubbleView.hEaseBubbleView+GifEaseBubbleView+Image中的UIImageView相应的改成了MMImageView

CustomMessageCell

- (void)setCustomModel:(id<IMessageModel>)model
{
	...
	else if ([model.mmExt[TEXT_MESG_TYPE] isEqualToString:TEXT_MESG_FACE_TYPE]) {
		...
		NSString *emojiCode = nil;
        if (model.mmExt[TEXT_MESG_DATA]) {
            emojiCode = model.mmExt[TEXT_MESG_DATA][0][0];
        }

        [self.bubbleView.imageView setImageWithEmojiCode:emojiCode];
        ...
	}
	...
}

gif表情 CustomMessageCell

- (void)setCustomModel:(id<IMessageModel>)model
{
	...
	else if ([model.mmExt[TEXT_MESG_TYPE] isEqualToString:TEXT_MESG_WEB_TYPE]) {
		...
		NSDictionary *msgData = model.mmExt[TEXT_MESG_DATA];
        NSString *webStickerUrl = msgData[WEBSTICKER_URL];
        NSString *webStickerId = msgData[WEBSTICKER_ID];
        [self.bubbleView.imageView setImageWithUrl:webStickerUrl gifId:webStickerId];
        ...
	}
	...
}

###7. demo中的其他修改 0. 相应的类中引用头文件。

  1. CustomMessageCell中的isCustomBubbleView用于根据消息类型来标识消息view是否需要自定义。
- (BOOL)isCustomBubbleView:(id<IMessageModel>)model
{
    BOOL flag = NO;
    switch (model.bodyType) {
        case EMMessageBodyTypeText:
        {
            if ([model.mmExt objectForKey:@"em_emotion"]) {
                flag = YES;
            }
            else if ([model.mmExt[TEXT_MESG_TYPE] isEqualToString:TEXT_MESG_EMOJI_TYPE]) {
                flag = YES;
            }
            else if ([model.mmExt[TEXT_MESG_TYPE] isEqualToString:TEXT_MESG_FACE_TYPE]) {
                flag = YES;
            }
            else if ([model.mmExt[TEXT_MESG_TYPE] isEqualToString:TEXT_MESG_WEB_TYPE]) {
                flag = YES;
            }
        }
            break;
        default:
            break;
    }    return flag;
    
}
  1. EaseMessageCell 布局相关
//BQMM集成 便于布局记录下的参数
@property (nonatomic) CGFloat bubbleWidth UI_APPEARANCE_SELECTOR; //default 200;
@property (nonatomic) CGSize gifSize;

//BQMM集成
- (void)_updateBubbleWidthConstraint
{
    [self removeConstraint:self.bubbleMaxWidthConstraint];
    
    self.bubbleMaxWidthConstraint = [NSLayoutConstraint constraintWithItem:self.bubbleView attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:self.bubbleWidth];
    [self addConstraint:self.bubbleMaxWidthConstraint];
}

- (void)setBubbleWidth:(CGFloat)bubbleWidth
{
    _bubbleWidth = bubbleWidth;
    [self _updateBubbleWidthConstraint];
}

EaseBaseMessageCell

- (void)layoutSubviews
{
    [super layoutSubviews];
    _bubbleView.backgroundImageView.image = self.model.isSender ? self.sendBubbleBackgroundImage : self.recvBubbleBackgroundImage;
    switch (self.model.bodyType) {
        case eMessageBodyType_Text:
        {
            //BQMM集成
            if ([self.model.mmExt[@"txt_msgType"] isEqualToString:@"emojitype"]) {
                CGFloat bubbleMaxWidth = self.bubbleMaxWidth;
                if ([UIDevice currentDevice].systemVersion.floatValue == 7.0) {
                    bubbleMaxWidth = 200;
                }
                bubbleMaxWidth -= (self.leftBubbleMargin.left + self.leftBubbleMargin.right + self.rightBubbleMargin.left + self.rightBubbleMargin.right)/2;
                CGSize size = [MMTextParser sizeForMMTextWithExtData:self.model.mmExt[@"msg_data"] font:self.messageTextFont maximumTextWidth:bubbleMaxWidth];
                [self setBubbleWidth:size.width + 25];
            }else if ([self.model.mmExt[TEXT_MESG_TYPE] isEqualToString:TEXT_MESG_FACE_TYPE]){
                //BQMM 集成 计算图片尺寸
                CGSize size =
                [MMImageView sizeForImageSize:CGSizeMake(kEMMessageImageSizeHeight, kEMMessageImageSizeHeight) imgMaxSize:CGSizeMake(kEMMessageImageSizeHeight, kEMMessageImageSizeHeight)];
                [self setBubbleWidth:size.width + self.bubbleMargin.left + self.bubbleMargin.right];
            }else if ([self.model.mmExt[TEXT_MESG_TYPE] isEqualToString:TEXT_MESG_WEB_TYPE]){
                //BQMM 集成 计算图片尺寸
                //宽最大200 高最大 150
                CGSize size =
                [MMImageView sizeForImageSize:CGSizeMake(self.model.gifSize.width, self.model.gifSize.height) imgMaxSize:CGSizeMake(200, 150)];
                [self setBubbleWidth:size.width + self.bubbleMargin.left + self.bubbleMargin.right];
            }

        }
            break;
        ...

CustomMessageCell

//BQMM集成   自定义气泡view的布局
- (void)setCustomBubbleView:(id<IMessageModel>)model
{
    if ([model.mmExt objectForKey:@"em_emotion"]) {
        [_bubbleView setupGifBubbleView];
        
        _bubbleView.imageView.image = [UIImage imageNamed:model.failImageName];
    }
    else if ([model.mmExt[@"txt_msgType"] isEqualToString:@"emojitype"]) {
        [_bubbleView setupMMTextBubbleViewWithModel:model];
    }
    else if ([model.mmExt[@"txt_msgType"] isEqualToString:@"facetype"] || [model.mmExt[TEXT_MESG_TYPE] isEqualToString:TEXT_MESG_WEB_TYPE]) {
        [_bubbleView setupGifBubbleView];
        
        _bubbleView.imageView.image = [UIImage imageNamed:model.failImageName];
    }
}

//BQMM集成   更新气泡view的布局
- (void)updateCustomBubbleViewMargin:(UIEdgeInsets)bubbleMargin model:(id<IMessageModel>)model
{
    if ([model.mmExt[TEXT_MESG_TYPE] isEqualToString:TEXT_MESG_EMOJI_TYPE]) {
        [_bubbleView updateMMTextMargin:bubbleMargin];
    }
    else if ([model.mmExt[TEXT_MESG_TYPE] isEqualToString:TEXT_MESG_FACE_TYPE] || [model.mmExt[TEXT_MESG_TYPE] isEqualToString:TEXT_MESG_WEB_TYPE]) {
        [_bubbleView updateGifMargin:bubbleMargin];
    }
}

//BQMM集成  根据消息类型设置cell的 reuseCellIdentifier
+ (NSString *)cellIdentifierWithModel:(id<IMessageModel>)model
{
    if ([model.mmExt objectForKey:@"em_emotion"]) {
        return model.isSender?@"EaseMessageCellSendGif":@"EaseMessageCellRecvGif";
    }
    else if ([model.mmExt[TEXT_MESG_TYPE] isEqualToString:TEXT_MESG_EMOJI_TYPE]) {
        return model.isSender?@"EaseMessageCellSendMMText":@"EaseMessageCellRecvMMText";
    }
    else if ([model.mmExt[TEXT_MESG_TYPE] isEqualToString:TEXT_MESG_FACE_TYPE]) {
        return model.isSender?@"EaseMessageCellSendGif":@"EaseMessageCellRecvGif";
    }else if([model.mmExt[TEXT_MESG_TYPE] isEqualToString:TEXT_MESG_WEB_TYPE]) {
        return model.isSender?@"EaseMessageCellSendWebSticker":@"EaseMessageCellRecvWebSticker";
    }
    else {
        NSString *identifier = [EaseBaseMessageCell cellIdentifierWithModel:model];
        return identifier;
    }
}

//BQMM集成  计算消息cell的高度
+ (CGFloat)cellHeightWithModel:(id<IMessageModel>)model
{
    if ([model.mmExt objectForKey:@"em_emotion"]) {
        return 100;
    }
    else {
        CGFloat height = [EaseBaseMessageCell cellHeightWithModel:model];
        return height;
    }
}

+ (CGFloat)cellHeightWithModel:(id<IMessageModel>)model
{
    ...
    switch (model.bodyType) {
        case eMessageBodyType_Text://BQMM集成
        {
            UIFont *textFont = cell.messageTextFont;
            if ([model.mmExt[@"txt_msgType"] isEqualToString:@"emojitype"]) {
                CGSize size = [MMTextParser sizeForMMTextWithExtData:model.mmExt[@"msg_data"] font:textFont maximumTextWidth:bubbleMaxWidth];
                
                height += (size.height > 20 ? size.height : 20) + 4;
            }
            else if ([model.mmExt[TEXT_MESG_TYPE] isEqualToString:TEXT_MESG_FACE_TYPE]) {
                //BQMM 集成 计算图片尺寸
                CGSize size =
                [MMImageView sizeForImageSize:CGSizeMake(kEMMessageImageSizeHeight, kEMMessageImageSizeHeight) imgMaxSize:CGSizeMake(kEMMessageImageSizeHeight, kEMMessageImageSizeHeight)];
                height += size.height;
            }else if([model.mmExt[TEXT_MESG_TYPE] isEqualToString:TEXT_MESG_WEB_TYPE]) {
                //BQMM 集成 计算图片尺寸
                //宽最大200 高最大 150
                CGSize size =
                [MMImageView sizeForImageSize:CGSizeMake(model.gifSize.width, model.gifSize.height) imgMaxSize:CGSizeMake(200, 150)];
                height += size.height;
            }
            else {
                NSString *text = model.text;
                CGRect rect = [text boundingRectWithSize:CGSizeMake(bubbleMaxWidth, CGFLOAT_MAX) options:NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading attributes:@{NSFontAttributeName:textFont} context:nil];
                height += (rect.size.height > 20 ? rect.size.height : 20) + 10;
            }
        }
        ...
        default:
            break;
    }
    
    height += EaseMessageCellPadding;
    model.cellHeight = height;
    return height;
}
  1. 关闭商店相关

EaseChatToolbar 添加商店关闭观察者

- (instancetype)initWithFrame:(CGRect)frame
{
    ...
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(backToUserInterface)
                                                 name:@"SMEmotionDismissShopNotification"
                                               object:nil];
    ...
}

//去掉商店关闭观察者
- (void)dealloc
{
    //BQMM集成
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

//BQMM集成 处理商店关闭事件
- (void)backToUserInterface {
    self.moreButton.selected = NO;
    if (!_inputTextView.isFirstResponder) {
        [_inputTextView becomeFirstResponder];
    }
    [[MMEmotionCentre defaultCentre] attachEmotionKeyboardToInput:_inputTextView];
    self.faceButton.selected = YES;
}

###8. gif搜索模块UI定制

BQMM_GIF是一整套gif搜索UI模块的实现源码,可用于直接使用或用于参考实现gif搜索,及gif消息的发送解析。 ####gif搜索源码说明 gif相关的功能由MMGifManager集中管理:

1.设置搜索模式的开启和关闭;指定输入控件

- (void)setSearchModeEnabled:(BOOL)enabled withInputView:(UIResponder<UITextInput> *_Nullable)input;

2.设置是否显示搜索出的表情内容;指定表情内容的显示位置

- (void)setSearchUiVisible:(BOOL)visible withAttatchedView:(UIView *_Nullable)attachedView;

3.通过MMSearchModeStatus管理搜索模式的开启和关闭及搜索内容的展示和收起(MMSearchModeStatus可自由调整)

typedef NS_OPTIONS (NSInteger, MMSearchModeStatus) {
    MMSearchModeStatusKeyboardHide = 1 << 0,         //收起键盘
    MMSearchModeStatusInputEndEditing = 1 << 1,         //收起键盘
    MMSearchModeStatusInputBecomeEmpty = 1 << 2,     //输入框清空
    MMSearchModeStatusInputTextChange = 1 << 3,      //输入框内容变化
    MMSearchModeStatusGifMessageSent = 1 << 4,       //发送了gif消息
    MMSearchModeStatusShowTrendingTriggered = 1 << 5,//触发流行表情
    MMSearchModeStatusGifsDataReceivedWithResult = 1 << 6,     //收到gif数据
    MMSearchModeStatusGifsDataReceivedWithEmptyResult = 1 << 7,     //搜索结果为空
};
- (void)updateSearchModeAndSearchUIWithStatus:(MMSearchModeStatus)status;

###9. UI定制

SDK通过MMTheme提供一定程度的UI定制。具体参考类说明MMTheme

创建一个MMTheme对象,设置相关属性, 然后[[MMEmotionCentre defaultCentre] setTheme:]即可修改商店和键盘样式。

###10. 清除缓存

调用clearCache方法清除缓存,此操作会删除所有临时的表情缓存,已下载的表情包不会被删除。建议在- (void)applicationWillTerminate:(UIApplication *)application 方法中调用。

###11. 设置APP UserId

开发者可以用setUserId方法设置App UserId,以便在后台统计时跟踪追溯单个用户的表情使用情况。