在 Android 中,若是須要使用的到 Emoji 表情,你會發如今某些設備上,有一些 Emoji 表情會被以豆腐塊 「☐」 的形式顯示,這是由於當前設備並不支持這個 Emoji 表情。html
而在 Android Support 中,新增長了一個 EmojiCompat 來專門解決這個問題,EmojiCompat 對 Android 4.4(Api Level 19)以及以後的系統,進行 Emoji 的擴展支持!android
接下來咱們就來了解使用 EmojiCompat 的全部細節!算法
既然要用到 Emoji ,咱們先來了解一下什麼是 Emoji。c#
Emoji 是能夠被插入文字中的圖形符號。它是一個日本語,e 表示"繪",moji 表示 "文字" ,連在一塊兒就是 「繪文字」。設計模式
Emoji 最先是上個世紀 90 年代的時候,又日本電信商率先支持,就是爲了在短信中,插入表情,來加強短信的體驗。2007 年,Apple 在 iPhone 中支持了 Emoji,才讓它在全球範圍內流行起來。bash
早期的時候,Emoji 的實現是將一些特殊的符號組合替換成圖片表情,例如 :)
替換成 😊 ,這樣的解決方案會致使很難將 Emoji 的表情標準化,並且表達的範圍也有限。app
2010年開始,Unicode 開始爲 Emoji 分配碼點,也就是說,在那以後的 Emoji 符號,就是一個字體,它會被渲染爲圖片顯示。iphone
Emoji 因爲其表達情緒的特色,被廣受歡迎。Emoji 的國際標準在 2015 年出臺,如今已是 5.0 版本了,而在 2018 年,將發佈 Emoji 6.0(以後會重命名爲 Emoji 11,其實就是 Emoji 5.0 的升級版) 版本的標準。ide
截止到如今,Emoji 5.0 中,被列入 Unicode 的已經有 2623 個了。學習
具體細節能夠在這個網站中查詢到:
http://www.unicode.org/emoji/charts/full-emoji-list.html
到這裏你們應該清楚,Emoji 在標準化後,其實就是一個字體,它被 Unicode 分配了固定的碼點,通常咱們就用標準的 Unicode 來標識一個惟一的 Emoji。
雖然 Emoji 已經被標準化了,可是不一樣平臺由於使用的字體不一樣,致使一樣的 Unicode 表明的 Emoji,被渲染顯示出不一樣的效果。
例如這裏舉的例子,標準的 Emoji U+1F601,在 Apple 和 Android 中,雖然一樣表示一個笑臉,可是渲染的效果是不同的,這一點咱們須要瞭解到。
一個標準的 Emoji ,實際上是有多種表示方法的,舉個例子,先看看前面說的笑臉 U+1F601
。
Code、UTF-八、Surrogates 這些形式,均可以表示這個笑臉的 Emoji。一般這個 Emoji 表情是來自用戶輸入的數據或者服務端傳遞過來的數據,雖然這些形式均可以表示這個 Emoji,可是不一樣的格式就須要不一樣的形式來解析。
正常來講,咱們推薦使用 Surrogates 傳遞 Emoji,例如:\uD83D\uDE01
,它自己就是一個 Unicode 的編碼,是通用的,能夠在 TextView 中直接使用就能夠顯示。
但是,假如咱們獲得的並非 Surrogates ,而是 Code ,例如 1F601
,這樣咱們就須要進行額外的處理了。其實也很簡單,通過幾步轉換就能夠作到。
String(Character.toChars(Integer.parseInt("1F601", 16)))
複製代碼
例子中使用的是 Kotlin 代碼,不過應該不影響閱讀。
將生成的 String 對象,傳遞給 TextView,若是是當前設備支持的 Emoji,就能夠正常顯示了。
上一小節介紹的方式,其實咱們是沒有作任何特殊處理的,徹底是以來設備本身的字體庫來進行 Emoji 渲染的。這就會致使有一些 Emoji 在某些設備上顯示不出來的狀況。
使用這種方案,我用我手邊的設備運行以後,來看看顯示的效果。
很清晰的看到,這裏有一些 Emoji 沒法顯示,會被顯示成一個豆腐塊 「☐」 ,而這並非咱們想要的。
接下來咱們來看看使用 EmojiCompat 如何來處理它。
根據官方文檔描述,EmojiCompat 支持庫主要是爲了讓 Android 設備,達到最新的 Emoji 符號的顯示效果,它能夠防止應用中,出現以豆腐塊 「☐」 的形式來顯示 Emoji,雖然它僅僅只是由於你當前的設備沒有這個字體而已。經過 EmojiCompat ,你的設備無需等待 Android 系統更新,就能夠得到最新的 Emoji 表情顯示效果。
EmojiCompat 支持庫,最低支持到 Android 4.4(Api Level 19) 的系統設備。
EmojiCompat 提供兩種字體的支持方式,它們分別是:
這兩種使用方式,除了引用的庫不一樣以外,最根本的緣由在於,可下載的字體的方式,會在首次啓動的時候檢查本地是否有該字體,沒有的話會從網上下載最新的 Emoji 字體;而本地捆綁的方式,會在 App 打包的過程當中,植入一個最新的 Emoji 字體文件,而後遇到不能支持的 Emoji,就會從這個字體文件中,加載資源而且渲染。
目前官方使用的是 NotoColorEmojiCompat.ttf
字體文件,後面會詳細講解到。
我想你應該發現了,本地捆綁的方式會嵌入一個字體文件,無形中增大了 Apk 安裝包的體積,可是可下載字體的方式,又徹底依賴 Google 服務,因此在國內基本上是處於殘廢狀態,在這個大環境下,咱們這裏只能選擇本地捆綁的方式來使用 EmojiCompat。
不管使用哪一種方式配置字體,對於 EmojiCompat 而言,實際上是不關心的,它只須要判斷當前設備是否支持這個 Emoji,支持就使用系統內置的,不支持的話,就使用 EmojiSpans 來替換 CharSequence,來達到替換渲染的效果。
EmojiCompat 的運行原理以下圖所示。
既然可下載的 Emoji 字體,須要配合 Google 服務,那這裏就再也不過多介紹了。
本文主要講解如何使用本地捆綁的方式,使用 EmojiCompat。
第一步,須要添加 Gradle 依賴。
dependencies {
...
compile "com.android.support:support-emoji-bundled:27.0.2"
}
複製代碼
第二步,初始化 EmojiCompat。
初始化 EmojiCompat ,須要兩個步驟。
EmojiCompat.init()
方法,將前面生成的 config 傳遞給它進行初始化。這個過程越早越好,由於初始化是耗時的,它會去加載打包的時候,嵌入的 Emoji 字體文件,因此大概須要消耗 150ms 的時間,而且佔用大概 200kb 的內存。
第三步,使用 EmojiCompat。
初始化完成以後,就剩下如何使用它了。
EmojiCompat 的處理邏輯,前面已經使用圖片描述清楚了。它會加載一個 Emoji 字體,而後判斷當前設備是否支持須要顯示的 Emoji,若是不支持,則使用 EmojiSpans 替換它,最終將處理過的 CharSequence 設置到 TextView 上。
而這個過程,EmojiCompat 提供了很是簡單的方法,process()
。
從它的簽名能夠看出,它接受一個 CharSequence 並處理它,而後返回一個 CharSequence。
舉個例子:這裏轉換一個笑臉的表情。
EmojiCompat.get().process("笑臉: \uD83D\uDE01")
複製代碼
process()
須要接受一個 Unicode 的字符,因此若是獲得的數據是前面提到的 Emoji Code 的話,就須要一步單獨的轉換。process()
內部已經幫咱們完成了轉換,這些細節都無需咱們關心,咱們只須要將它返回的 CharSequence 設置給 TextView 就能夠了。
在實際項目中,若是每次都須要經過 EmojiCompat.get().process()
對字符串進行處理,其實也挺麻煩的。爲此 Google 還爲開發者提供了對應控件支持。
若是須要使用它,就須要引入新的依賴庫。
dependencies {
compile "com.android.support:support-emoji-appcompat:27.0.2"
}
複製代碼
引入以後,就能夠直接在 XML 中使用 EmojiAppCompat 提供的控件。
使用 support-emoji-appcompat
只是節省了咱們 process()
的步驟,可是依然須要 init()
。
你能夠一直使用 progress()
或者使用 EmojiAppCompatXxx
控件,可是若是你想要自定義一個控件來顯示 Emoji,就須要使用 EmojiCompat 提供的另外兩個幫助類。
這兩個使用起來很是簡單,一個用於處理純展現的控件,一個用於處理有輸入的狀態的控件,很是的簡潔明瞭。
哪怕不記得了,看看 EmojiAppCompatTextView 和 EmojiAppCompatEditView 中的實現方式就能夠了。
這裏拿 EmojiAppCompatTextView 舉例子,只須要在幾個關鍵的位置上,使用 EmojiTextViewHelper 的對應方法便可。
總體來講 EmojiCompat 仍是很好用的,不管使用哪一種方式加載它,實際上咱們都不須要作過多的干預。
這裏參考官方文檔,列舉最多見的幾個問題。
一、下載字體的下載策略是怎麼樣的?
Emoji 字體在第一次使用的時候,會檢測是否存在於當前設備,若是不存在則在子線程中進行下載。
二、初始化須要多長時間?
當本地已經有字體以後,初始化 EmojiCompat 大約須要 150 毫秒。
三、EmojiCompat 支持庫,會使用多少內存?
目前,Emoji 字體被徹底加載以後,會使用大約 200kb 的內存。
四、在 Android 4.4 如下的設備上,使用 EmojiAppCompatXxx 控件會發生什麼狀況?
EmojiCompat 內部已經作了兼容處理,在低版本上就和使用普通的 AppCompatXxx 控件同樣。
五、本地捆綁的 Emoji 字體文件,大約有多大?
本地捆綁的 Emoji 字體文件 NotoColorEmojiCompat.ttf
,會在打包的時候嵌入到 assets
目錄下,如今實際狀況來看大小有 7.4MB,這會直接形成 Apk 的增大。
更多的細節,仍是建議你們閱讀官方文檔。
https://developer.android.google.cn/guide/topics/ui/look-and-feel/emoji-compat.html
在實際使用 EmojiCompat 的過程當中,還遇到了一個不能算缺陷的缺陷。
咱們來回憶一下以前提到過的,EmojiCompat 的處理機制。
它只有在當前設備遇到不被支持的 Emoji 的時候,纔會從 Support Font 中加載字體,若是有,它會使用 System Font 。
這也不能怪 EmojiCompat 的設計者,它的出發點,是爲了解決 Emoji 在某些設備中,顯示豆腐塊 「☐」 的問題,而不關心它究竟是不是顯示最新的 Emoji,是在解決有無的問題。
這就很尷尬了,其實有時候 Android 設備內置支持的字體,顯示的效果並很差,咱們先來看看使用 EmojiCompat 先後的對比效果。
左邊是沒有使用 EmojiCompat 的效果,而右邊是使用過的效果。
很清晰的能夠看到 EmojiCompat 幫我補齊了我當前設備部支持的那些 Emoji 表情,可是並無將 Android 的果凍表情替換爲標準的 Emoji 表情。
那麼,若是咱們想要讓它顯示最新的 Emoji ,咱們須要這麼辦呢?
前面提到,自從 Emoji 開始被標準化以後,其實就是一個字體,而且 EmojiCompat 也是幫咱們捆綁嵌入了一個字體包在 assets
目錄下,那咱們只須要讓咱們顯示的 TextView 加載這個 Emoji 字體,就能夠解決這個問題。
有了思路,咱們就來試試這個解決方案是否可行。
到此,咱們就能夠經過調用 loadEmoji()
方法,讓 TextView 顯示 Emoji ,來看看對比的效果。
從左到右,分別是:默認 Emoji、EmojiCompat、Emoji Font 的顯示效果。
密密麻麻的表情有點多,密集恐懼症請放過我,😆!
固然,這裏只是提供一個解決方案,採用此方案的狀況下,基本上全部 4.4 以上的機型,均可以顯示最新的 Emoji,若是對 Emoji 的顯示效果有要求,這也不失爲一個解決方案。
到此,就是我所瞭解的 Android 下的 Emoji。
看完本文你有什麼收穫?或者你有什麼更好的關於 Emoji 的建議,歡迎在留言討論!
今天在承香墨影公衆號的後臺,回覆『成長』。我會送你一些我整理的學習資料,包含:Android反編譯、算法、設計模式、虛擬機、Linux、Kotlin、Python、爬蟲、Web項目源碼。
推薦閱讀: