博客 / 詳情

返回

還在為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。

user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.