Android Jetpack - Emoji表情符号初探
在 Android 中,如果需要使用的到 Emoji 表情,你會發現在某些設備上,有一些 Emoji 表情會被以豆腐塊 “?” 的形式顯示,這是因為當前設備并不支持這個 Emoji 表情。
而在 Android Support 中,新增加了一個 EmojiCompat 來專門解決這個問題,EmojiCompat 對 Android 4.4(Api Level 19)以及之后的系統,進行 Emoji 的擴展支持!
接下來我們就來了解使用 EmojiCompat 的所有細節!
一、什么是 Emoji?
既然要用到 Emoji ,我們先來了解一下什么是 Emoji。
Emoji 是可以被插入文字中的圖形符號。它是一個日本語,e 表示"繪",moji 表示 "文字" ,連在一起就是 “繪文字”。
Emoji 最早是上個世紀 90 年代的時候,又日本電信商率先支持,就是為了在短信中,插入表情,來增強短信的體驗。2007 年,Apple 在 iPhone 中支持了 Emoji,才讓它在全球范圍內流行起來。
早期的時候,Emoji 的實現是將一些特殊的符號組合替換成圖片表情,例如 :) 替換成 ? ,這樣的解決方案會導致很難將 Emoji 的表情標準化,而且表達的范圍也有限。
2010年開始,Unicode 開始為 Emoji 分配碼點,也就是說,在那之后的 Emoji 符號,就是一個字體,它會被渲染為圖片顯示。
Emoji 由于其表達情緒的特點,被廣受歡迎。Emoji 的國際標準在 2015 年出臺,現在已經是 5.0 版本了,而在 2018 年,將發布 Emoji 6.0(之后會重命名為 Emoji 11,其實就是 Emoji 5.0 的升級版) 版本的標準。
截止到現在,Emoji 5.0 中,被列入 Unicode 的已經有 2623 個了。
具體細節可以在這個網站中查詢到:
www.unicode.org/emoji/chart…
到這里大家應該清楚,Emoji 在標準化后,其實就是一個字體,它被 Unicode 分配了固定的碼點,一般我們就用標準的 Unicode 來標識一個唯一的 Emoji。
雖然 Emoji 已經被標準化了,但是不同平臺因為使用的字體不同,導致同樣的 Unicode 代表的 Emoji,被渲染顯示出不同的效果。
例如這里舉的例子,標準的 Emoji U+1F601,在 Apple 和 Android 中,雖然同樣表示一個笑臉,但是渲染的效果是不一樣的,這一點我們需要了解到。
二、Emoji 在 Android 中的現狀
2.1 如何使用 Emoji?
一個標準的 Emoji ,其實是有多種表示方法的,舉個例子,先看看前面說的笑臉 U+1F601。
Code、UTF-8、Surrogates 這些形式,都可以表示這個笑臉的 Emoji。通常這個 Emoji 表情是來自用戶輸入的數據或者服務端傳遞過來的數據,雖然這些形式都可以表示這個 Emoji,但是不同的格式就需要不同的形式來解析。
正常來說,我們推薦使用 Surrogates 傳遞 Emoji,例如:\uD83D\uDE01,它本身就是一個 Unicode 的編碼,是通用的,可以在 TextView 中直接使用就可以顯示。
可是,假如我們得到的并不是 Surrogates ,而是 Code ,例如 1F601,這樣我們就需要進行額外的處理了。其實也很簡單,經過幾步轉換就可以做到。
String(Character.toChars(Integer.parseInt("1F601", 16))) 復制代碼例子中使用的是 Kotlin 代碼,不過應該不影響閱讀。
將生成的 String 對象,傳遞給 TextView,如果是當前設備支持的 Emoji,就可以正常顯示了。
2.2 Emoji 顯示不出來情況
上一小節介紹的方式,其實我們是沒有做任何特殊處理的,完全是以來設備自己的字體庫來進行 Emoji 渲染的。這就會導致有一些 Emoji 在某些設備上顯示不出來的情況。
使用這種方案,我用我手邊的設備運行之后,來看看顯示的效果。
很清晰的看到,這里有一些 Emoji 無法顯示,會被顯示成一個豆腐塊 “?” ,而這并不是我們想要的。
接下來我們來看看使用 EmojiCompat 如何來處理它。
三、使用 EmojiCompat
3.1 什么是 EmojiCompat
根據官方文檔描述,EmojiCompat 支持庫主要是為了讓 Android 設備,達到最新的 Emoji 符號的顯示效果,它可以防止應用中,出現以豆腐塊 “?” 的形式來顯示 Emoji,雖然它僅僅只是因為你當前的設備沒有這個字體而已。通過 EmojiCompat ,你的設備無需等待 Android 系統更新,就可以獲得最新的 Emoji 表情顯示效果。
3.2 如何使用 EmojiCompat
EmojiCompat 支持庫,最低支持到 Android 4.4(Api Level 19) 的系統設備。
EmojiCompat 提供兩種字體的支持方式,它們分別是:
這兩種使用方式,除了引用的庫不同之外,最根本的原因在于,可下載的字體的方式,會在首次啟動的時候檢查本地是否有該字體,沒有的話會從網上下載最新的 Emoji 字體;而本地捆綁的方式,會在 App 打包的過程中,植入一個最新的 Emoji 字體文件,然后遇到不能支持的 Emoji,就會從這個字體文件中,加載資源并且渲染。
目前官方使用的是 NotoColorEmojiCompat.ttf 字體文件,后面會詳細講解到。
我想你應該發現了,本地捆綁的方式會嵌入一個字體文件,無形中增大了 Apk 安裝包的體積,但是可下載字體的方式,又完全依賴 Google 服務,所以在國內基本上是處于殘廢狀態,在這個大環境下,我們這里只能選擇本地捆綁的方式來使用 EmojiCompat。
無論使用哪種方式配置字體,對于 EmojiCompat 而言,其實是不關心的,它只需要判斷當前設備是否支持這個 Emoji,支持就使用系統內置的,不支持的話,就使用 EmojiSpans 來替換 CharSequence,來達到替換渲染的效果。
EmojiCompat 的運行原理如下圖所示。
3.3 本地捆綁的字體配置方式
既然可下載的 Emoji 字體,需要配合 Google 服務,那這里就不再過多介紹了。
本文主要講解如何使用本地捆綁的方式,使用 EmojiCompat。
第一步,需要添加 Gradle 依賴。
dependencies {...compile "com.android.support:support-emoji-bundled:27.0.2" } 復制代碼第二步,初始化 EmojiCompat。
初始化 EmojiCompat ,需要兩個步驟。
這個過程越早越好,因為初始化是耗時的,它會去加載打包的時候,嵌入的 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 就可以了。
3.4 Emoji AppCompat Widgets
在實際項目中,如果每次都需要通過 EmojiCompat.get().process() 對字符串進行處理,其實也挺麻煩的。為此 Google 還為開發者提供了對應控件支持。
如果需要使用它,就需要引入新的依賴庫。
dependencies {compile "com.android.support:support-emoji-appcompat:27.0.2" } 復制代碼引入之后,就可以直接在 XML 中使用 EmojiAppCompat 提供的控件。
使用 support-emoji-appcompat 只是節省了我們 process() 的步驟,但是依然需要 init() 。
3.5 自定義控件支持 Emoji
你可以一直使用 progress() 或者使用 EmojiAppCompatXxx 控件,但是如果你想要自定義一個控件來顯示 Emoji,就需要使用 EmojiCompat 提供的另外兩個幫助類。
- EmojiTextViewHelper
- EmojiEditViewHelper
這兩個使用起來非常簡單,一個用于處理純展示的控件,一個用于處理有輸入的狀態的控件,非常的簡潔明了。
哪怕不記得了,看看 EmojiAppCompatTextView 和 EmojiAppCompatEditView 中的實現方式就可以了。
這里拿 EmojiAppCompatTextView 舉例子,只需要在幾個關鍵的位置上,使用 EmojiTextViewHelper 的對應方法即可。
3.6 EmojiCompat面臨的問題
整體來說 EmojiCompat 還是很好用的,無論使用哪種方式加載它,實際上我們都不需要做過多的干預。
這里參考官方文檔,列舉最常見的幾個問題。
1、下載字體的下載策略是怎么樣的?
Emoji 字體在第一次使用的時候,會檢測是否存在于當前設備,如果不存在則在子線程中進行下載。
2、初始化需要多長時間?
當本地已經有字體之后,初始化 EmojiCompat 大約需要 150 毫秒。
3、EmojiCompat 支持庫,會使用多少內存?
目前,Emoji 字體被完全加載之后,會使用大約 200kb 的內存。
4、在 Android 4.4 以下的設備上,使用 EmojiAppCompatXxx 控件會發生什么情況?
EmojiCompat 內部已經做了兼容處理,在低版本上就和使用普通的 AppCompatXxx 控件一樣。
5、本地捆綁的 Emoji 字體文件,大約有多大?
本地捆綁的 Emoji 字體文件 NotoColorEmojiCompat.ttf,會在打包的時候嵌入到 assets 目錄下,現在實際情況來看大小有 7.4MB,這會直接造成 Apk 的增大。
更多的細節,還是建議大家閱讀官方文檔。
developer.android.google.cn/guide/topic…
四、EmojiCompat 的缺陷?
在實際使用 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 Jetpack - Emoji表情符号初探的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 利用jmap和MAT等工具查看JVM运行
- 下一篇: UiBot Creator v1.2火热