最近在做一个聊天的应用,有一个问题就是iOS跟Android的Emoji字符不对应导致显示不正常。因为iOS这部分是先做的,所以便让负责安卓的同学想办法兼容iOS的编码表,不过安卓的同学想尽办法也没办法搞到Apple Color Emoji的编码表,不过他却找到了有几百张Emoji

最近在做一个聊天的应用,有一个问题就是iOS跟Android的Emoji字符不对应导致显示不正常。因为iOS这部分是先做的,所以便让负责安卓的同学想办法兼容iOS的编码表,不过安卓的同学想尽办法也没办法搞到Apple Color Emoji的编码表,不过他却找到了有几百张Emoji表情的图片,后来经过整理剩下180张是完整的放在项目里的,图片下载在这里.于是,我就利用这些图片来想办法跟现有的项目兼容。

之前的情况

iOS之前的Emoji部分,是用了这个文件夹里的类来产生所有的Emoji表情的unicode字符的,主要是做了一个映射和一定的排序和筛选,来使这些表情不会太杂乱。内部的实现可以说是看起来比较复杂但是思路很简单的,就不做详细赘述了.安卓的同学说安卓有一个可以图文混排的View,叫做EditText的.

于是,安卓的同学就希望我将iOS这边也是改成图文混排的方式,发送表情的时候就只是发送图片的名字,然后我们再约定每个图片的名字以一个特殊的字符开始并以一个特殊的字符结束,不过想到现有的方案要推倒重来实在不妥,而且用图片很难保证在每个分辨率的手机上都能有很好的效果。似乎手Q就是用的这种方案,因为我在看安卓手机发来的emoji表情的时候有很明显的锯齿…

另外在服务器方面,之前iOS发送Emoji表情跟发送文字是一起的,即是以unicode的方式发送和存储的。

我的方案

我想到安卓的同学之所以没办法搞到Apple Color Emoji的编码表,是因为这个字体只在苹果系上才有,所以不如我来搞定那个编码表吧,把Emoji的unicode编码和图片对应起来,然后在每次Model传数据给View的时候,将图片名解析成unicode编码,然后在保存至Model的时候将unicode编码转换成图片名就好了,这样子只需要设置字体的大小就能控制emoji表情的大小了,而且以前的代码几乎不用修改。

方法很简单,但就是花时间,所以才特地整理了这篇文章可以省大家的力气。我先是将所有的emoji Code和Emoji表情打印到文件里,然后跟图片文件进行比对,整理出了他们的映射表.

然后就需要跟服务器和安卓的同学约定好Emoji开始的字符和结束的字符就好了,我们的定义如下:

#define EmojiBegin 0x02

#define EmojiEnd 0x03

接下来就是解析工作了,还是很简单的,我是写了一个category来完成这些工作,代码如下:

NSString+Emoji.h

//

// NSString+Emoji.h

// EmojiAdapter

//

// Created by Jeason on 14-8-11.

// Copyright (c) 2014年 EmojiAdapter. All rights reserved.

//

#import

@interface NSString (Emoji)

/**

* Encode a string contains emoji string to a string contains emoji filename.

* Just encode each substring to filename, if it hs no associating filename, it will return nil.

* @return the encoded string

*/

- (NSString *)encodeString;

/**

* Decode the string contains file names to String contains emoji string.

*

* @return the result string

*/

- (NSString *)decodeString;

/**

* Generate the encode dictionary to encode an emoji string to filename

*

* @return the encode dictionary

*/

+ (NSDictionary *)encodeDictionary;

@end

NSString+Emoji.m

//

// NSString+Emoji.m

// EmojiAdapter

//

// Created by Jeason on 14-8-11.

// Copyright (c) 2014年 EmojiAdapter. All rights reserved.

//

#import "NSString+Emoji.h"

#import "Emoji.h"

#define EmojiBegin 0x02

#define EmojiEnd 0x03

@implementation NSString (Emoji)

-(NSString *)decodeString {

__block BOOL isEmojiBegin = false;

__block NSString *emojiFileName = @""; //temp var to store the file name

__block NSMutableString *result = [NSMutableString stringWithString:@""];

[self enumerateSubstringsInRange:NSMakeRange(0, [self length])

options:NSStringEnumerationByComposedCharacterSequences //setperate as composed character

usingBlock:^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop) {

const char *utf8Str = [substring UTF8String];

char aChar = [substring characterAtIndex:0]; //a unicode substr's length is 2

if ( aChar == EmojiBegin && strlen(utf8Str) == 1 ) { //卧槽,句号的unicode编码刚好第一个字符就是0x02

isEmojiBegin = YES;

} else if ( aChar == EmojiEnd && strlen(utf8Str) == 1 ) { //if it is in end

isEmojiBegin = NO;

NSString *emoji = [emojiFileName decodeEmojiString]; //decode the filename

if ( emoji != nil ) { //if decode succ

[result appendString:emoji]; //add to result

}

emojiFileName = @""; //clear file name

} else {

if ( isEmojiBegin ) { //the next substring is part of filename

emojiFileName = [emojiFileName stringByAppendingString:substring];

} else { //the next substring is the normal string

[result appendString:substring];

}

}

}];

return [NSString stringWithString:result];

}

/**

* Decode a single file name to emoji string

*

* @return the decode emoji string

*/

- (NSString *)decodeEmojiString {

NSString *plistName;

if ( [self length] >= 3 ) { //if the filename is valid

if ( [self characterAtIndex:0] == 'f' ) {

if ( [self characterAtIndex:1] == 'l' ) {

//flower

plistName = @"EmojiFlower";

} else {

//face

plistName = @"EmojiFace";

}

} else if ( [self characterAtIndex:0] == 's' ) {

if ( [self characterAtIndex:1] == 't' ) {

//status

plistName = @"EmojiStatus";

} else {

//symbol

plistName = @"EmojiSymbol";

}

} else if ( [self characterAtIndex:0] == 'm' ) {

//meal

plistName = @"EmojiMeal";

}

NSString *filePath = [[NSBundle mainBundle] pathForResource:plistName ofType:@"plist"];

NSDictionary *decodeDict = [[NSDictionary alloc] initWithContentsOfFile:filePath];//read the plist file

NSInteger emojiCode = [[decodeDict objectForKey:self] intValue];

return [Emoji emojiWithCode:emojiCode];

} else {

return @"";

}

}

+ (NSDictionary *)encodeDictionary {

NSArray *plistNames = @[@"ToEmojiFace", @"ToEmojiFlower", @"ToEmojiStatus", @"ToEmojiSymbol", @"ToEmojiMeal"];

NSMutableDictionary *toEmojiDict = [NSMutableDictionary dictionary];

for (NSString *pName in plistNames) {

NSString *filePath = [[NSBundle mainBundle] pathForResource:pName ofType:@"plist"];

NSDictionary *dict = [[NSDictionary alloc] initWithContentsOfFile:filePath];

[toEmojiDict addEntriesFromDictionary:dict];

}

return toEmojiDict;

}

- (NSString *)encodeString {

NSDictionary *toEmojiDict = [NSString encodeDictionary];

__block NSMutableString *result = [NSMutableString stringWithString:@""];

[self enumerateSubstringsInRange:NSMakeRange(0, [self length])

options:NSStringEnumerationByComposedCharacterSequences

usingBlock:^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop) {

NSString *encodeStr = toEmojiDict[substring];

encodeStr = encodeStr == nil ? substring : [encodeStr encodeEmojiString];

[result appendString:encodeStr];

}];

return [NSString stringWithString:result];

}

/**

* Encode emoji string with a prefix and a postfix

*

* @return the encoded emoji string

*/

-(NSString *)encodeEmojiString {

return [NSString stringWithFormat:@"%c%@%c",EmojiBegin, self, EmojiEnd];

}

@end

这样子,就可以在需要写数据库和发送网络的时候调用

someChatMsg = [someChatMsg encodeString];

然后在想要显示UI的部分调用

someChatMsg = [someChatMsg decodeString];

而且,在Emoji.m里为每个Emoji查找一次看有没有对应的文件名来筛选出可以在iOS跟安卓通用的Emoji表情啦!完整的项目Demo在这里

补充一句

为什么要筛选只有180个表情呢,因为发现不论是手Q还是微信还是自带的Emoji键盘,它都是每行有7个表情,一页有3行,最后一个是删除键,这样子180个表情就有180 / (7*3-1) = 9页啦,所以180个已经是非常足够了的,太多页也会让用户失去耐心~

iOS和Android的Emoji表情同步方案 Jeason George at Jeason August 24, 2014.

android ios emoji表情,iOS和Android的Emoji表情同步方案相关推荐

  1. android5.1和ios差距,Android 5.1和IOS运行流畅度比较Android获胜!

    实践是检验真相的唯一标准,它一直是发布它的人们的教育,所以我一直认为Android不会比ios更加流畅,但是由于我吃了苹果,所以我有了改变了我以前的看法. 它是ip6p,系统是ios8.4,比较And ...

  2. Drawable的Tint变色(让Android也能有iOS那么方便的图片色调转换)

    2019独角兽企业重金招聘Python工程师标准>>> Drawable的Tint变色(让Android也能有iOS那么方便的图片色调转换) 字数590 阅读475 评论0 喜欢1 ...

  3. android ios 7 双环,安卓机泪奔 库克嘲笑Android 7安装率不及iOS 10零头

    原标题:安卓机泪奔 库克嘲笑Android 7安装率不及iOS 10零头 北京时间6月1日凌晨1:00,苹果一年一度的WWDC全球开发者大会如期召开,作为苹果最重要的软件盛会,此次苹果不仅更新的tvO ...

  4. android没有捂脸表情,Emoji神器 | 如果你也喜欢[捂脸]表情

    晚上好:) 「一」 关于Emoji 还记得三年前第一次用上智能手机,那时还很年轻,还喜欢刷QQ空间,对于各种表情也是爱不释手,右键盗图(已右键)成了当时流行的话. 慢慢的随着年纪增长,也不如以前那样热 ...

  5. android ios web兼容,js与android iOS 交互兼容

    js与android iOS 交互兼容 在Android与js交互方面还是要比iOS方便很多,而UIWebView只暴漏出- (BOOL)webView:(UIWebView *)webView sh ...

  6. android 调出键盘表情_Android 软键盘和emoji表情切换方案,和微信几乎一样的体验...

    注意:本项目还有一个小坑.第一次进去的时候有时候输入框没有得到焦点,没有弹出软键盘,所以不能更好的量取软键盘高度,给了一个默认值787 软键盘默认高度.所以可以忽略不计,一旦弹出了软键盘,这个高度就被 ...

  7. video.js android,VideoJS + HTML5自动播放失败,适用于Android 2.3+和IOS 4+

    我的VideoJS和HTML5项目针对更新的Web浏览器(较新版本的FireFox和Chrome)以及移动浏览器(Android2.3 +和IOS4 +).VideoJS + HTML5自动播放失败, ...

  8. android加法服务类,iOS越来越像Android:苹果简单做加法远离精致

    原标题:iOS越来越像Android:苹果简单做加法远离精致 刚刚结束的WWDC2016的主题演讲中,苹果为我们带来了最新的iOS 10系统,官方称本次iOS 10的推出有着多大10项的重要更新,在用 ...

  9. android 侧滑删除功能,200行代码让你在Android中完美实现iOS版侧滑删除效果

    使用几个月的IOS之后,发现IOS中侧滑删除俺就 大家好,自己开始学习Android已经差不多半年了吧,前前后后看了不少的博客获益匪浅.渐渐的随着技术的提升,慢慢感觉网上其它的一些功能的实现又不是那么 ...

  10. android 表情退格,讯飞输入法Android V8.1.8212 嘘-别说话全套emoji表情上

    emoji表情大家都不陌生,一个个"小黄脸"在手机聊天场景中高频出现.随着蹿红网络,emoji表情甚至跑进大电影中成为主角.为何大家如此喜欢它?因此各式表情很像不同心情的自己,开心 ...

最新文章

  1. javascript-对混合字母/数字数组进行排序
  2. 为什么神经网络会把乌龟识别成步枪?现在的 AI 值得信任吗?
  3. win7 修复计算机 黑屏,boot bcd修复win7 旗舰版系统黑屏错误代码0xc0000034的解决方法...
  4. 数码管流动显示(自己的单片机)
  5. JFinalOA导出Excel
  6. html label 两端对齐,如果实现表单的label文字两端对齐
  7. el-select change事件传多个参数_第8天 | 14天搞定Vue3.0,事件处理(详细)
  8. vmtools 安装不上的方法 我这里介绍下vm14 Ubuntu的系统
  9. ORA-12514: TNS:listener does not currently know of service …
  10. 网站页面直接显示html代码 转义html代码 excel导入题库 解决方法
  11. php curl getinfo详解,php curl getinfo
  12. origin做主成分分析图_Origin如何进行主成分分析
  13. 不用U盘从linux重装win系统,不用U盘和光盘安装win7旗舰版系统
  14. 直播软件搭建时如何在视频通话中加入美颜处理
  15. JVM内部锁升级过程(偏向锁,轻量级锁,重量级锁)
  16. 2021年终总结——拾起好习惯,让自己变得更加优秀
  17. 检测ip和port是否可连接
  18. Android:删除腾讯X5内核的右上角设备信息
  19. 怎样使用word模板?两分钟教你搞定!
  20. 图像去噪,深度学习去噪,普通方法

热门文章

  1. 研究生教育学科专业目录(2022年)与研究生教育学科专业目录管理办法
  2. WebEx Recorder 录屏软件
  3. iTextSharp 使用详解
  4. 屏幕取色软件ColorPix
  5. Qt文件路径:QDir
  6. 简单介绍——【汇总统计数据】工具(ArcMap)
  7. Qt配置opencv
  8. 常用cmd操作Redis的命令
  9. GD32F103学习笔记(1)——搭建环境、编译烧写
  10. 《艾伦图灵传:如谜的解谜者》阅读笔记