乐趣区

关于android:还在为Android表情开发烦恼吗快来试试Android-Emoji吧

一、什么是 Emoji

1.1 Emoji 背景

Emoji 是一种 表情符号,来自日语词汇“絵文字”(假名为“えもじ”,读音即 emoji)。它的创造者是日本人栗田穰崇 (Shigetaka Kurita),他将眼光投向儿时的各类元素以获取灵感,如日本漫画和日本汉字等。“日本漫画中有许多不一样的符号。漫画家会画出一些表情,体现一我的满头大汗或是迸发出一个想法时头上呈现一个灯泡。”同时,从日本汉字中他失去了一种能力,用简略的字符来表白“机密”和“爱”等抽象概念。

晚期的 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 14.0,整个 Emoji 表情也达到了 3600 多个。具体细节能够查看 unicode 官网


不过,尽管 Emoji 曾经被标准化,然而不同平台因为应用的字体不同,导致同样的 Unicode 代表的 Emoji,被渲染显示进去的成果也会不一样,如下。

1.2 Android 对 Emoji 的反对

在 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,目前这个库能向下兼容到 Android 4.4,其次要指标就是为了让咱们的 Android 设施能够反对最新的 emoji 表情,避免最新的 emoji 表情在咱们的手机上显示为☐。EmojiCompat 通过 CharSequence 文本中的 emoji 对应的 unicode 编码来辨认 emoji 表情,将他们替换成 EmojiSpans,最初再将 EmojiSpan 渲染成对应的 emoji 表情符号。

二、EmojiCompat

2.1 什么是 EmojiCompat

EmojiCompat 是 Google 官网给咱们提供的一个 Emoji 表情兼容库,最低反对到 Android 4.4(Api Level 19) 的零碎设施,它能够避免利用中,呈现以信封的模式来显示 Emoji,尽管它仅仅只是因为你以后的设施没有这个字体而已。通过 EmojiCompat,你的设施无需期待 Android 零碎更新,就能够取得最新的 Emoji 表情显示成果,原理如下。


能够看到,Emoji 的一个显示原理,EmojiCompat 会判断以后设施是否反对这个 Emoji,如果反对则还是应用零碎内置的字体加载,如果不反对,则应用 EmojiSpan 来进行替换,从而达到替换渲染的成果。

2.2 配置 EmojiCompat

EmojiCompat 提供两种字体的反对形式,它们别离是可下载的字体配置和本地捆绑的字体配置。

  • 可下载的字体配置 :可下载的字体的形式会在首次启动 app 的时候查看本地是否有该字体,没有的话会从网上下载最新的 Emoji 字体,而后遇到不反对的 Emoji,就会从这个字体文件中,加载资源并且渲染。
  • 本地捆绑的字体配置 :本地捆绑的形式会在 App 打包的过程中,植入一个最新的 Emoji 字体文件,而后遇到不反对的 Emoji,就会从这个字体文件中,加载资源并且渲染。

2.2.1 本地字体配置形式

首先,须要在 build.gradle 增加 emoji-bundled 依赖,如下。

implementation 'androidx.emoji:emoji-bundled:1.1.0'

而后,初始化 构建本地捆绑字体配置 EmojiCompat,因为初始化是耗时的,所以最好提前进行初始化,比方 Application 中。

class MyApplication : Application() {override fun onCreate() {super.onCreate()
        initEmoji()}

    private fun initEmoji() {val config: EmojiCompat.Config = BundledEmojiCompatConfig(this)
        config.setReplaceAll(true)
        config.registerInitCallback(object : InitCallback() {override fun onInitialized() {// 初始化胜利回调}

            override fun onFailed(@Nullable throwable: Throwable?) {// 初始化失败回调}
        })
        EmojiCompat.init(config)
    }
}

2.2.2 可下载的字体配置

可下载的字体须要在 build.gradle 增加 emoji 依赖,如下。

implementation 'androidx.emoji:emoji:1.1.0'

而后,构建可下载字体配置初始化 EmojiCompat,初始化的时候须要传入字体,如下。

private fun initEmojiCompat() {
        val fontRequest = FontRequest(
            "com.google.android.gms.fonts",
            "com.google.android.gms",
            "Noto Color Emoji Compat",
            R.array.emoji_list
        )
        val config: EmojiCompat.Config = FontRequestEmojiCompatConfig(this, fontRequest)
        config.setReplaceAll(true)
        config.registerInitCallback(object : InitCallback() {override fun onInitialized() {// 初始化胜利回调}

            override fun onFailed(throwable: Throwable?) {// 初始化失败回调}
        })
        EmojiCompat.init(config)
    }

2.3 应用 EmojiCompat

初始化之后,接下来就是在业务开发中应用 EmojiCompat。EmojiCompat 的解决逻辑,后面曾经讲的很分明了:首先,它会加载一个 Emoji 字体,而后判断以后设施是否反对须要显示的 Emoji,如果不反对,则应用 EmojiSpans 替换它,最终将解决过的 CharSequence 设置到 TextView 上。而这个过程,EmojiCompat 提供了一个 process() 办法。

从代码中能够看到,process() 承受一个 CharSequence 并解决它,而后返回一个 CharSequence。举个例子:咱们应用 process() 转换一个笑脸的表情。

EmojiCompat.get().process("笑脸:\uD83D\uDE01")

在理论我的项目中,如果每次都须要通过 EmojiCompat.get().process() 对字符串进行解决,其实挺麻烦的。为此,EmojiCompat 提供了 EmojiTextView,EmojiButton,EmojiEditText 等控件。

<androidx.emoji.widget.EmojiTextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="&#129316;" />

    <androidx.emoji.widget.EmojiButton
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="&#10084;" />

    <androidx.emoji.widget.EmojiEditText
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="&#128527;" />

EmojiCompat 会判断以后设施是否反对这个 Emoji,如果反对则还是应用零碎内置的字体加载,如果不反对,则应用 EmojiSpan 来进行替换,从而达到替换渲染的成果。这是在你没设置 config.setReplaceAll(true) 的状况下,而如果你设置了 config.setReplaceAll(true),那么所有的 Emoji 表情都会应用 EmojiSpan 替换并渲染。

2.4 自定义 Emoji 控件

当然,咱们也能够自定义 Emoji 控件,自定义 Emoji 控件能够参考下 EmojiAppCompatTextView 和 EmojiAppCompatEditView 中的实现。

三、Emoji2

因为之前的版本 EmojiCompat 只兼容 Android 4.4 以上的设施,对于 4.4 如下的设施它的行为跟一般的 Android 组件是没有差异的。并且,EmojiCompat 的初始化工夫大概只须要 150 毫秒,内存的占用大略在 200kb,所以最近 Google 官网提供了 Emoji2 库。应用之前,须要先增加依赖,如下。

    def emoji2_version = "1.0.0"
    implementation "androidx.emoji2:emoji2:$emoji2_version"
    implementation "androidx.emoji2:emoji2-views:$emoji2_version"
    implementation "androidx.emoji2:emoji2-views-helper:$emoji2_version"

Emoji2 一共提供了 4 个控件,EmojiButton、EmojiEditText、EmojiExtractTextLayout 和 EmojiTextView,应用形式和之前的差不多,比方。

<androidx.emoji2.widget.EmojiTextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="&#129316;"
        tools:ignore="MissingConstraints" />

    <androidx.emoji2.widget.EmojiButton
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="&#10084;"
        tools:ignore="MissingConstraints" />

    <androidx.emoji2.widget.EmojiEditText
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="&#128527;"
        tools:ignore="MissingConstraints" />

既然 Emoji 这么乏味,还不快在你的利用中应用 AppCompat 1.4。

退出移动版