美文网首页iOS之功能细节
【OC-环信】环信3.x自定义表情实现

【OC-环信】环信3.x自定义表情实现

作者: 苜蓿鬼仙 | 来源:发表于2018-06-26 10:03 被阅读0次

    首语

    最近一直在搞一个 2015 年的项目,需要把对应项目中的环信 2.x 升级到 环信 3.x,而在本项目中使用的环信 SDK 是 3.4.1 版本的。


    图片-环信 Hyphenate 3.4.1

    而项目中的需求之一就是自定义表情,不使用苹果系统的 Emoji 表情。同时也查了网上的相关资料,发现还是比较少的,所以打算在此记录一下相关笔记。

    自定义表情的实质

    自定义表情,实际上也是通过发送文本消息一样发送出去,只不过是对文本进行了特殊处理——编码转换。

    常见的自定义表情,一般都是提供一组表情素材图片,然后通过编码,将表情素材图片与对应的编码进行一一绑定。无论发送消息还是接收消息时,实际上都是文本消息。通过在本地客户的对消息进行处理,对于发出去的消息,将图片通过一一对应的编码转成文本字符发出去;对于接收的消息,将接收的文本字符转成一一对应的图片进行显示。

    自定义表情实现

    1、对自定义表情素材图片进行编码转码绑定

    ① 先导入对应要展示的自定义表情素材图片。


    图片 - 自定义表情素材图片导入

    ② 找到 EaseUI/EMUIKit/Util/ 目录下的 EaseConvertToCommonEmoticonsHelper 类,该类主要是处理表情编码的。该类已经默认处理了系统 Emoji 表情的编码转码工作。

    图片 - EaseConvertToCommonEmoticonsHelper 处理的系统 Emoji 表情编码转码方法

    ③ 对该类进行方法扩展,扩展的方法主要是实现自己自定义表情的编码转码工作。

    注意:如果不想侵入 EaseUI 的源码,可以选择通过 Category 扩展的方式进行添加方法。

    #pragma mark - EaseConvertToCommonEmoticonsHelper.h
    
    // 自定义表情编码转码
    + (NSDictionary *)emotionsDictionary;
    + (NSArray*)emotionsArray;
    
    #pragma mark - EaseConvertToCommonEmoticonsHelper.m
    
    
    + (NSArray*)emotionsArray {
    
        NSMutableArray *array = [NSMutableArray arrayWithObjects:@"[爱你]",@"[奥特曼]",@"[拜拜]",@"[悲伤]",@"[鄙视]",@"[闭嘴]",@"[馋嘴]",@"[吃惊]",@"[打哈欠]",@"[叮]", @"[愤怒]",@"[感冒]",@"[鼓掌]",@"[哈哈]",@"[害羞]",@"[汗]",@"[呵呵]",@"[无语]",@"[哼]",@"[花心]",@"[可爱]",@"[可怜]",@"[酷]",@"[困]",@"[傲慢]", @"[累]",@"[男孩儿]",@"[怒]",@"[怒骂]",@"[女孩儿]",@"[钱]",@"[亲亲]",@"[生病]",@"[失望]",@"[衰]",@"[书呆子]",@"[睡觉]",@"[思考]",@"[太开心]", @"[丢笑]",@"[吐]",@"[兔子]",@"[抠鼻]",@"[委屈]",@"[熊猫]",@"[嘻嘻]",@"[嘘]",@"[阴险]",@"[疑问]",@"[右哼哼]",@"[晕]",@"[抓狂]",@"[猪头]", @"[左怪脸]",@"[左哼哼]",@"[给力]",@"[互粉]",@"[囧]",@"[萌]",@"[神马]",@"[帅]",@"[V5]",@"[囍]",@"[织]",@"[不要]",@"[肥皂]",@"[good]",@"[来]",@"[OK]",@"[拳头]",@"[弱]",@"[握手]",@"[胜利]",@"[赞]",@"[最差]",@"[爱心]",@"[伤心]",@"[冰棍]",@"[蛋糕]",@"[飞机]",@"[风扇]",@"[啤酒]",@"[红领带]",@"[话筒]",@"[咖啡]",@"[蜡烛]",@"[礼物]",@"[绿领带]",@"[汽车]",@"[实习]",@"[手机]",@"[手套]",@"[网球]",@"[围脖]",@"[围观]",@"[帽子]",@"[西瓜]",@"[音乐]",@"[照相]",@"[钟表]",@"[自行车]",@"[足球]",@"[乌云]",@"[落叶]",@"[沙尘暴]",@"[太阳]",@"[微风]",@"[鲜花]", nil];
        
        return array;
    }
    
    + (NSDictionary *)emotionsDictionary {
    
        NSMutableArray *array = [NSMutableArray arrayWithObjects:@"[爱你]",@"[奥特曼]",@"[拜拜]",@"[悲伤]",@"[鄙视]",@"[闭嘴]",@"[馋嘴]",@"[吃惊]",@"[打哈欠]",@"[叮]", @"[愤怒]",@"[感冒]",@"[鼓掌]",@"[哈哈]",@"[害羞]",@"[汗]",@"[呵呵]",@"[无语]",@"[哼]",@"[花心]",@"[可爱]",@"[可怜]",@"[酷]",@"[困]",@"[傲慢]", @"[累]",@"[男孩儿]",@"[怒]",@"[怒骂]",@"[女孩儿]",@"[钱]",@"[亲亲]",@"[生病]",@"[失望]",@"[衰]",@"[书呆子]",@"[睡觉]",@"[思考]",@"[太开心]", @"[丢笑]",@"[吐]",@"[兔子]",@"[抠鼻]",@"[委屈]",@"[熊猫]",@"[嘻嘻]",@"[嘘]",@"[阴险]",@"[疑问]",@"[右哼哼]",@"[晕]",@"[抓狂]",@"[猪头]", @"[左怪脸]",@"[左哼哼]",@"[给力]",@"[互粉]",@"[囧]",@"[萌]",@"[神马]",@"[帅]",@"[V5]",@"[囍]",@"[织]",@"[不要]",@"[肥皂]",@"[good]",@"[来]",@"[OK]",@"[拳头]",@"[弱]",@"[握手]",@"[胜利]",@"[赞]",@"[最差]",@"[爱心]",@"[伤心]",@"[冰棍]",@"[蛋糕]",@"[飞机]",@"[风扇]",@"[啤酒]",@"[红领带]",@"[话筒]",@"[咖啡]",@"[蜡烛]",@"[礼物]",@"[绿领带]",@"[汽车]",@"[实习]",@"[手机]",@"[手套]",@"[网球]",@"[围脖]",@"[围观]",@"[帽子]",@"[西瓜]",@"[音乐]",@"[照相]",@"[钟表]",@"[自行车]",@"[足球]",@"[乌云]",@"[落叶]",@"[沙尘暴]",@"[太阳]",@"[微风]",@"[鲜花]", nil];
        
        NSMutableDictionary *dic = [NSMutableDictionary dictionary];
        for (int i=0; i<array.count; i++) {
            [dic setObject:[NSString stringWithFormat:@"%03d", i+1] forKey:array[i]];
        }
        
        return dic;
    }
    
    图片 - EaseConvertToCommonEmoticonsHelper.h 扩展自定义表情编码转码方法 图片 - EaseConvertToCommonEmoticonsHelper.m 扩展自定义表情编码转码方法

    2、在 didFinishLaunchingWithOptions 中初始化设置自定义表情相关代码

    环信社区中给的参考资料说是尽量放在 HelpDeskUI 中,但是我发现在 环信 3.4.1 中并没有这个类文件,所以就选择了放在 didFinishLaunchingWithOptions 中进行初始化设置,从而保证使用。

    • 调用了 EaseEmotionEscape 类中的两个方法:
      • (void) setEaseEmotionEscapePattern:(NSString*)pattern;
      • (void) setEaseEmotionEscapeDictionary:(NSDictionary*)dict;
    • 这两个方法是保证在聊天发送表情消息时,输入框中显示的是对应的表情,而不是对应的编码字符。必须要设置的。
    #pragma mark - AppDelegate.m
    
    
    [[EaseEmotionEscape sharedInstance] setEaseEmotionEscapePattern:@"\\[[^\\[\\]]{1,3}\\]"];
    [[EaseEmotionEscape sharedInstance] setEaseEmotionEscapeDictionary:[EaseConvertToCommonEmoticonsHelper emotionsDictionary]];
    
    图片 - 初始化设置自定义表情相关代码

    3、设置聊天界面自定义表情相关代码

    在聊天界面,如果需要自定义表情,则需要重写 EaseMessageViewController 类的关于表情的方法:

      • (NSArray*)emotionFormessageViewController:(EaseMessageViewController *)viewController;
    • 该方法属于 EaseMessageViewControllerDataSource 的代理方法;
    • @property (weak, nonatomic) id<EaseMessageViewControllerDataSource> dataSource;
    • 所以需要记得实现绑定代理协议,否则重写的 emotionFormessageViewController 方法会不执行的:
    • self.dataSource = self;
    /** 替换表情 **/
    - (NSArray*)emotionFormessageViewController:(EaseMessageViewController *)viewController {
        /** 系统表情(此处本来应该是隐藏的,为了方便看系统表情实现,所以代码暂时未屏蔽,此种情况下显示的,应该是两个表情容器;如果不需要使用系统表情容器,这段代码直接屏蔽即可![](https://diycode.b0.upaiyun.com/photo/2018/08bab5caa05e59f66f3fd5c4e74f969b.png)
    [](https://diycode.b0.upaiyun.com/photo/2018/62e3bf4d9164e37f9a20c67532d16534.jpg)
     **/
        NSMutableArray *emotions = [NSMutableArray array];
        for (NSString *name in [EaseEmoji allEmoji]) {
            EaseEmotion *emotion = [[EaseEmotion alloc] initWithName:@"" emotionId:name emotionThumbnail:name emotionOriginal:name emotionOriginalURL:@"" emotionType:EMEmotionDefault];
            [emotions addObject:emotion];
        }
        EaseEmotion *temp = [emotions objectAtIndex:0];
        EaseEmotionManager *managerDefault = [[EaseEmotionManager alloc] initWithType:EMEmotionDefault emotionRow:3 emotionCol:7 emotions:emotions tagImage:[UIImage imageNamed:temp.emotionId]];
        
    
        /** 自定义表情 **/
        NSMutableArray *emotions2 = [NSMutableArray array];
        NSMutableArray *nameArr2 = [NSMutableArray arrayWithCapacity:0];
        NSString *name2 = nil;
        for (int i=1; i<=[[EaseConvertToCommonEmoticonsHelper emotionsArray] count]; i++) {
            name2 = [NSString stringWithFormat:@"%03d",i];
            [nameArr2 addObject:name2];
        }
        int j=0;
        for (NSString *name2 in [EaseConvertToCommonEmoticonsHelper emotionsArray]) {
            EaseEmotion *emotion = [[EaseEmotion alloc] initWithName:@"" emotionId:name2 emotionThumbnail:nameArr2[j] emotionOriginal:nameArr2[j] emotionOriginalURL:@"" emotionType:EMEmotionPng];
            [emotions2 addObject:emotion];
            j++;
        }
        EaseEmotion *temp2 = [emotions2 objectAtIndex:0];
        EaseEmotionManager *managerDefault2 = [[EaseEmotionManager alloc] initWithType:EMEmotionPng emotionRow:3 emotionCol:7 emotions:emotions2 tagImage:[UIImage imageNamed:temp2.emotionThumbnail]];
    
        return @[managerDefault, managerDefault2];
    }
    
    图片 - 重写 emotionFormessageViewController 方法

    4、调整自定义表情容器显示大小

    如果需要调整自定义表情容器的显示,则需要找到对应的视图 View。而此处我们则需要找到 EaseUI/EMUIKit/Views/conversation/toolbar/FaceView 目录下的 EaseFacialView 类文件,就是在此处进行调整的。

    通过此处的代码我们可以了解到,该自定义表情容器 View 是一个 UICollectionView,且是纵向的,即数据源不是从左向右依次的,而是从上到下,再从左到右依次进行展现的。

    此处我们可以对以下涉及位置的 UICollectionView 代理方法进行调整:

    • 设置表情尺寸大小:
      • (CGSize)collectionView:(UICollectionView )collectionView layout:(UICollectionViewLayout)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath;
    • 设置表情容器到边缘距离(会影响到表情间距):
      • (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section;
    • 设置表情行与行之间的间距(注意此时是纵向添加的,所以行与行间距应该是横向的):
      • (CGFloat)collectionView:(UICollectionView )collectionView layout:(UICollectionViewLayout)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section;
    • 设置表情与表情之间的间距(注意此时是纵向添加的,所以表情与表情的间距应该是纵向的):
      • (CGFloat)collectionView:(UICollectionView )collectionView layout:(UICollectionViewLayout)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section;

    此处我这边设置的是表情与表情间间距为 0,行与行之间的间距 15,距离边缘距离顶部、底部各为 5,左侧右侧各为 7.5,而这个左侧右侧的间距 7.5 正好取的是行与行之间间距的一半,防止按页滚动的时候发生偏移。

    #pragma mark - EaseFacialView.m
    
    
    /** 设置表情尺寸大小 **/
    - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
        
        EaseEmotionManager *emotionManager = [_emotionManagers objectAtIndex:indexPath.section];
        NSInteger maxRow = emotionManager.emotionRow;
        NSInteger maxCol = emotionManager.emotionCol;
        CGFloat itemWidth = self.frame.size.width / maxCol;
        CGFloat itemHeight = (self.frame.size.height) / maxRow;
    
        float width = (CGRectGetWidth(self.frame)-7.5*2-(emotionManager.emotionCol-1)*15)/emotionManager.emotionCol;
        if (emotionManager.emotionType == EMEmotionPng) {
            return CGSizeMake(width,width);
        }
        return CGSizeMake(itemWidth, itemHeight);
    }
    
    /** 设置表情容器到边缘距离(会影响到表情间距) **/
    - (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section {
    
        EaseEmotionManager *emotionManager = [_emotionManagers objectAtIndex:section];
        if (emotionManager.emotionType == EMEmotionPng) {
            return UIEdgeInsetsMake(5.f, 7.5f, 5.f, 7.5f);
        }
        return UIEdgeInsetsMake(0, 0, 0, 0);
    }
    
    /** 设置表情行与行之间的间距(注意此时是纵向添加的,所以行与行间距应该是横向的) **/
    - (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section {
    
        EaseEmotionManager *emotionManager = [_emotionManagers objectAtIndex:section];
        if (emotionManager.emotionType == EMEmotionPng) {
            return 15.f;
        }
        
        return 0.0f;
    }
    
    /** 设置表情与表情之间的间距(注意此时是纵向添加的,所以表情与表情的间距应该是纵向的) **/
    - (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section {
    
        EaseEmotionManager *emotionManager = [_emotionManagers objectAtIndex:section];
        if (emotionManager.emotionType == EMEmotionPng) {
            return 0.f;
        }
        
        return 0.0f;
    }
    
    图片 - 调整自定义表情容器显示大小(上) 图片 - 调整自定义表情容器显示大小(下)

    至此,自定义表情完成!!!瞅瞅效果吧:

    图片 - 环信 3.4.1 自定义表情最终效果

    参考链接

    相关文章

      网友评论

        本文标题:【OC-环信】环信3.x自定义表情实现

        本文链接:https://www.haomeiwen.com/subject/nxjpyftx.html