什么是 emoji?
emoji 是一种 表情符号,来自日语词汇“絵文字”(假名为“えもじ”,读音即 emoji)
它的创造者是日本人栗田穰崇 ( Shigetaka Kurita ) ,他将目光投向儿时的各种元素以获取灵感,如日本漫画和日本汉字等。“日本漫画中有许多不同的符号。漫画家会画出一些表情,表现一个人满头大汗或是迸发出一个想法时头上出现一个灯泡。”同时,从日本汉字中他获得了一种能力,用简单的字符来表达“秘密”和“爱”等抽象概念。
image.png早期的 emoji 表情并没有一套统一的规范,日本的三大电信运营商,NTT DoCoMo,au/KDDI,Softbank 都各自有一套关于 Emoji 的编码规范,导致运营商用户之间发送 emoji 表情时无法显示。
直到2010年10月,随着 Unicode6.0 的发布,Emoji 的编码以及对应的表情图片正式被规范化,核心 Emoji 表情包含722个 Emoji 编码。
之后 2014年6月15日发布的 Unicode 7.0 规范以及 2016年6月22日发布的 Unicode 9 规范都不断地加入新的 emoji 表情,目前整个 emoji 表情已经达到了一千多个。
感兴趣的同学可以到这里查看所有表情对应的编码
Android 对 emoji 表情的兼容
很多同学可能并没有注意到 Android 设备上的 Emoji 表情
一般情况下,我们在手机上进行操作时, 只有使用了输入法自带的表情及 emoji 表情才会在文本中产生 emoji 编码。
image.png image.png在 Android 4.4 之前, Android 并不支持 emoji 表情,当时的解决方案主要是通过 imageSpan 配合 spannableString,来替换掉文字中的 emoji unicode 编码符号。
从 Android 4.4 开始, 官方开始了 emoji 表情的支持,实现原理基本就是通过把 emoji 表情内置在系统的 ttf 字体库中,对文本进行过滤后显示出 emoji 表情。
由于不同 Android 版本内置的 ttf 字体库对 emoji 表情的版本支持程度不同,导致老版本的 Android 对最新的 emoji 表情支持不全,所以一些 在新的 unicode 版本规范中被加入的 emoji 表情在老的 Android 设备上会显示方框乱码。
为了处理这个问题,除去上文提到的 spannable 的处理方案,我们还可以通过定义自己的 ttf 字体库给文本空间指定字体来显示 emoji 表情。
EmojiCompat Support Library 的诞生
正是由于上文提到的兼容问题,Google 官方的 EmojiCompat Support Library 诞生了。
目前这个库能向下兼容到 Android 4.4,其主要目标就是为了让我们的 Android 设备能够支持最新的 emoji 表情,防止最新的 emoji 表情在我们的手机上显示为☐。
Emoji 对照EmojiCompat 通过 CharSequence 文本中的 emoji 对应的 unicode 编码来识别 emoji 表情,将他们替换成 EmojiSpans ,最后再将 EmojiSpan 渲染成对应的 emoji 表情符号。
emojiCompat处理过程对于 EmojiCompat 的使用,有两种配置方式:
Downloadable fonts configuration
Downloadable fonts 是 Android O 新增的一个功能,支持通过 google mobile service 远程拉取需要的字体库到本地来进行使用。
由于国内屏蔽了 Google Service ,所以这种方式在国内我们使用不了,这里我们就不做详细介绍了。
Bundled fonts configuration
Bundled fonts 即打包字体,就是使用本地打包好的 emoji 字体库来兼容 emoji 表情。
目前官方使用的是 NotoColorEmojiCompat.ttf
字体文件。
EmojiCompat 的使用
接下来我们来看看如何使用 emojiCompat 库
添加依赖库
首先我们在 build.gradle 中配置我们的依赖包,由于我们使用的是 Bundled fonts 的配置,所以我们需要先引入我们的 emoji bundle 库:
dependencies {
...
compile "com.android.support:support-emoji-bundled:$version"
}
这里我 $version 设置的版本是 26.0.0-beta1,如果编译过程中提示找不到依赖库,需要在 repositories 仓库配置中加入 Google 的 maven 地址:
allprojects {
repositories {
jcenter()
maven { url 'https://maven.google.com' }
}
}
接着我们引入 EmojiCompat 的组件库:
dependencies {
...
compile "com.android.support:support-emoji:26.0.0-beta1"
}
该组件库对应的 emojiCompat 组件:
<android.support.text.emoji.widget.EmojiTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<android.support.text.emoji.widget.EmojiEditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<android.support.text.emoji.widget.EmojiButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
如果你使用的是 AppCompat 库, 也可以直接添加 emojiCompat 的 compat 组件库
dependencies {
compile "com.android.support:support-emoji-appcompat:26.0.0-beta1"
}
该引用库对应的组件:
<android.support.text.emoji.widget.EmojiAppCompatTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<android.support.text.emoji.widget.EmojiAppCompatEditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<android.support.text.emoji.widget.EmojiAppCompatButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
compat 库跟非 compat 库之间的差别主要就是在使用的组件名称上,其他的方式基本一致。
初始化 EmojiCompat
在正式使用 EmojiCompat 之前我们还需要对其进行初始化
public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
EmojiCompat.Config config = new BundledEmojiCompatConfig(this);
EmojiCompat.init(config);
}
}
此时我们便可以使用上一步添加的 emojiCompat 组件来替换原有的 TextView、 EditText 以及 Button 组件了,当文本中遇到对应的 emoji 表情编码时就会自动替换为 emoji 表情了。
device-2017-06-30-134851.png
不通过组件使用 emojiCompat 兼容库
EmojiCompat 库通过 EmojiSpan 来渲染正确的表情图片,因此需要先将文本 CharSequence 根据 emoji 编码转换成对应的 EmojiSpan Spanned 实例。
EmojiCompat 专门提供了一个 process() 方法用于CHarSequence 实例的转换
使用这种方法,我们可以缓存处理过的实例而不是原始字符串,在需要使用的地方直接调用该实例,从而提高应用程序的性能。
TextView regularTextView = findViewById(R.id.regular_text_view);
CharSequence processed = EmojiCompat.get().process("neutral face \uD83D\uDE10");
regularTextView.setText(processed);
自定义 EmojiCompat 组件
除了上面提到的通过 EmojiCompat 的 process 方法转换 spanned 实例外,我们还可以通过官方提供的两个 widget helper 类来自定义我们的 TextView 以及 EditTextView 组件:
android.support.text.emoji.widget.EmojiTextViewHelper
android.support.text.emoji.widget.EmojiEditTextHelper
示例代码:
自定义Emoji TextView
public class MyTextView extends AppCompatTextView {
...
public MyTextView(Context context) {
super(context);
init();
}
...
private void init() {
getEmojiTextViewHelper().updateTransformationMethod();
}
@Override
public void setFilters(InputFilter[] filters) {
super.setFilters(getEmojiTextViewHelper().getFilters(filters));
}
@Override
public void setAllCaps(boolean allCaps) {
super.setAllCaps(allCaps);
getEmojiTextViewHelper().setAllCaps(allCaps);
}
private EmojiTextViewHelper getEmojiTextViewHelper() {
...
}
}
自定义 Emoji EditText
public class MyEditText extends AppCompatEditText {
...
public MyEditText(Context context) {
super(context);
init();
}
...
private void init() {
super.setKeyListener(getEmojiEditTextHelper().getKeyListener(getKeyListener()));
}
@Override
public void setKeyListener(android.text.method.KeyListener keyListener) {
super.setKeyListener(getEmojiEditTextHelper().getKeyListener(keyListener));
}
@Override
public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
InputConnection inputConnection = super.onCreateInputConnection(outAttrs);
return getEmojiEditTextHelper().onCreateInputConnection(inputConnection, outAttrs);
}
private EmojiEditTextHelper getEmojiEditTextHelper() {
...
}
}
总结
看了上面的使用步骤,EmojiCompat 的使用是不是很方便呢?
目前来说,EmojiCompat 只兼容 Android 4.4 以上的设备,对于 4.4 以下的设备,它的行为跟普通的 Android 组件没有差异。
EmojiCompat 的初始化时间大约只需要 150 毫秒,内存的占用大概在200kb,所以你可以放心大胆地去使用它。
这里是官方的 Demo 地址:
https://github.com/googlesamples/android-EmojiCompat
里面包含了 downloadable fonts 的使用,因为比较完善 ,所以就不放我自己的 Demo 啦,感兴趣的小伙伴赶紧去下载看看吧!
网友评论
之前的问题(在Demo基础上修改)解决了,但是现在遇到了一个新的问题,我重建了一个Project,没有用EmojiTextView,用的是Textview,然后CharSequence processed = EmojiCompat.get().process("neutral face \uD83D\uDE10");
regularTextView.setText(processed);
Application中也初始化了,但是最后却报没有初始化异常。
Caused by: java.lang.IllegalStateException: Not initialized yet
EmojiCompat.Config config = new BundledEmojiCompatConfig(this);
EmojiCompat.init(config);
比如我的emoji表情对应的Unicode是U+1F469,我应该怎么转换成“\uD83D\uDC69\u200D\uD83D\uDCBB”。
因为我看google的Demo中的写法不是U+1F469,而是“\uD83D\uDC69\u200D\uD83D\uDCBB”。
allprojects {
repositories {
jcenter()
maven { url 'https://maven.google.com' }
}
}
这段吗