一个能在字符串中识别出 Emoji 的简单工具
特性
支持 Unicode12 规范
基于 EBNF 状态机的 Emoji 判断,比正则表达式更易维护
准确判断含有 Emoji 的字符串长度
准确切割字符串不会断开 Emoji
长度判断
EmojiString.lengthEmojiReader.getTextLength♀11
🙂21
👱♂51
🏳️🌈61
👨👩👦👦111
在字符串中,一个 Emoji 由一个或多个 Unicode 码点(CodePoint)组成,一个码点可能由多个字符组成(取决于码点是否大于 0x010000),因此一个 Emoji 可能由数个字符组成。
很多业务都需要有字数的判断,比如用户昵称不能过长,发言内容有字数限制等等。如果不对 Emoji 进行特殊处理,往往会出现不符合用户预期的情况。
使用 EmojiReader.getTextLength 可以获取到文本的可视符号的长度,一个 Emoji 的长度为1。
//Java
String strWithEmoji = "我是一个😃";
int error = strWithEmoji.length(); //6
int correct = EmojiReader.getTextLength(strWithEmoji); //5
复制代码
//JavaScript
const strWithEmoji = '我是一个😃';
const error = strWithEmoji.length; //6
const correct = require('emoji-reader').getTextLength(strWithEmoji); //5
复制代码
表情切割
当显示文本过长时,通常我们会省略末尾的文本,并加上省略号。
但如果字符串中含有 Emoji ,切割字符串就很可能把 Emoji 切段,变成乱码。比如下面这个字符串:
"我是🙂😐😎💏"
经过 String.subString(0, 5) 处理后:
"我是🙂?"
因为多个 Unicode 码点共同组合才能完成一个 Emoji 的展示,通过切割后剩下的 Unicode 码点会表现出无法正常显示的乱码。
使用 EmojiReader.subSequence 可以按照一个 Emoji 长度为1来进行符合视觉预期的裁剪。
//JavaScript
import EmojiReader from 'emoji-reader'
//Java
import com.yy.mobile.emoji.EmojiReader
EmojiReader.subSequence("我是🙂😐😎💏", 0, 5) == "我是🙂😐😎"
复制代码
安装 (Javascript)
npm install --save emoji-reader
复制代码
安装 (Java/Android)
根目录的 build.gradle 添加:
allprojects {
repositories {
...
maven { url 'https://jitpack.io' }
}
}
复制代码
使用的模块的 build.gradle 中添加:
dependencies {
api 'com.github.YvesCheung.EmojiReader:lib:2.0.1'
}
复制代码
原理
Unicode 规范文档中给出了 Emoji 的语法,是一个EBNF范式的表达:
possible_emoji :=
flag_sequence
| zwj_element (\x{200D} zwj_element)+
flag_sequence :=
\p{RI} \p{RI}
zwj_element :=
\p{Emoji} emoji_modification?
emoji_modification :=
\p{EMod}
| \x{FE0F} \x{20E3}?
| tag_modifier
tag_modifier :=
[\x{E0020}-\x{E007E}]+ \x{E007F}
复制代码
这里简单地解释一下:
Emoji只有三种形式
第一种是国旗类的,由两个国家区域符组成
两个区域符号组成国旗的样例
第二种是由表情专属的码点加修饰符组成(修饰符可选)
单个码点组成的样例
码点加上修饰符的样例(此例中修饰符为 \uFE0F \20E3)
第三种是由多个第二种表情通过连接符组成
多个(码点 修饰符)相连的样例(连接符为 \u200D)
经典的全家福
通过全家福可以发现,\u1F469 和 \u1F466 都是独立的 Emoji 码点,可以表现出一个人像,当他们通过 \u200D 连接符组合后,就可以表现出一个多人像的新 Emoji 。
一个工程师 \u1F477 和一个女性别 \2640 \FE0F 组合起来,就可以表现出一个女工程师的新 Emoji 。
可选的修饰符 \uFE0F \u20E3 等等跟在独立的 Emoji 码点后面,可以起修改表现颜色/表现性别等作用。
通过修饰符和连接符就能把 Emoji 码点组合出千变万化的表情。