浅谈emoji(分析与使用)
?
近期在項(xiàng)目中遇到這么一個(gè)需求,使用顏文字替換按鍵圖標(biāo)。
之前對(duì)于顏文字有了解,微信,QQ中也經(jīng)常使用,但是如何實(shí)現(xiàn)的呢?一無(wú)所知……
對(duì)于這塊突然有了一點(diǎn)興趣,所以做這么一個(gè)分享,與其說(shuō)分享,不如說(shuō)探索更為準(zhǔn)確一點(diǎn)。
為何做這個(gè)分析探索,主要說(shuō)來(lái)以下原因:
使用顏文字替換按鍵圖標(biāo)能減少本身apk中圖片資源的使用,從而達(dá)到減少apk包大小。
做定制化系統(tǒng)的時(shí)候,使用顏文字能使代碼優(yōu)雅簡(jiǎn)潔,圖文混排一句代碼解決,多語(yǔ)言翻譯簡(jiǎn)單化。
做聊天社交,論壇咨詢類APP時(shí),顏文字(Emoji)能使聊天,評(píng)論,增強(qiáng)用戶體驗(yàn),也是這類app必不可少的一部分內(nèi)容。
一、什么是Emoji?
既然要用到?Emoji?,我們先來(lái)了解一下什么是?Emoji。
Emoji?是可以被插入文字中的圖形符號(hào)。它是一個(gè)日本語(yǔ),e?表示"繪",moji?表示?"文字"?,連在一起就是?“繪文字”。
Emoji?最早是上個(gè)世紀(jì)?90?年代的時(shí)候,又日本電信商率先支持,就是為了在短信中,插入表情,來(lái)增強(qiáng)短信的體驗(yàn)。2007?年,Apple?在?iPhone?中支持了?Emoji,才讓它在全球范圍內(nèi)流行起來(lái)。
早期的時(shí)候,Emoji?的實(shí)現(xiàn)是將一些特殊的符號(hào)組合替換成圖片表情,例如?:)?替換成?
,這樣的解決方案會(huì)導(dǎo)致很難將?Emoji?的表情標(biāo)準(zhǔn)化,而且表達(dá)的范圍也有限。
2010年開(kāi)始,Unicode?開(kāi)始為?Emoji?分配碼點(diǎn),也就是說(shuō),在那之后的?Emoji?符號(hào),就是一個(gè)字體,它會(huì)被渲染為圖片顯示。
Emoji?由于其表達(dá)情緒的特點(diǎn),被廣受歡迎。Emoji?的國(guó)際標(biāo)準(zhǔn)在?2015?年出臺(tái),現(xiàn)在已經(jīng)是?5.0?版本了,而在?2018?年,將發(fā)布?Emoji 6.0(之后會(huì)重命名為?Emoji 11,其實(shí)就是?Emoji 5.0?的升級(jí)版) 版本的標(biāo)準(zhǔn)。
截止到現(xiàn)在,Emoji 5.0?中,被列入?Unicode?的已經(jīng)有?2623?個(gè)了。
具體細(xì)節(jié)可以在這個(gè)網(wǎng)站中查詢到:
http://www.unicode.org/emoji/charts/full-emoji-list.html
到這里大家應(yīng)該清楚,Emoji?在標(biāo)準(zhǔn)化后,其實(shí)就是一個(gè)字體,它被?Unicode?分配了固定的碼點(diǎn),一般我們就用標(biāo)準(zhǔn)的?Unicode?來(lái)標(biāo)識(shí)一個(gè)唯一的?Emoji。
雖然?Emoji?已經(jīng)被標(biāo)準(zhǔn)化了,但是不同平臺(tái)因?yàn)槭褂玫淖煮w不同,導(dǎo)致同樣的?Unicode?代表的?Emoji,被渲染顯示出不同的效果。
二、Emoji?在?Android?中的現(xiàn)狀
2.1如何使用Emoji
emoji表情是一種表情符號(hào),在代碼中它現(xiàn)在其實(shí)是一組遵循Unicode的編碼,即每一個(gè)表情符號(hào)都對(duì)應(yīng)了一個(gè)Unicode編碼。更進(jìn)一步說(shuō),emoji表情實(shí)際上是一組Unicode編碼與一組表情描述之間的一一對(duì)應(yīng)。注意,這里所說(shuō)的不是表情圖片,而是表情描述。那么圖片的實(shí)現(xiàn)是由誰(shuí)來(lái)負(fù)責(zé)的呢?圖片是由各個(gè)系統(tǒng)或者軟件針對(duì)統(tǒng)一的表情描述來(lái)各自實(shí)現(xiàn)的,他們都遵循統(tǒng)一的Unicode編碼規(guī)范。也就是說(shuō)Unicode編碼其所對(duì)應(yīng)的表情描述是統(tǒng)一的,是所有人都要共同遵守的一套標(biāo)準(zhǔn)或者規(guī)范,而具體的表情圖片則可能因平臺(tái)的不同而產(chǎn)生差異,比如Android和ios。
在android中,我們可以只用go輸入法或者搜狗輸入發(fā)來(lái)輸入emoji表情,對(duì)于用戶這沒(méi)有任何問(wèn)題。但是對(duì)于程序員來(lái)說(shuō)如何在程序中輸入或者得到一個(gè)emoji表情呢?比如我們想通過(guò)textview.setText()方法來(lái)輸入一個(gè)emoji表情。
其實(shí)通過(guò)emoji表情的通用Unicode編碼就可以實(shí)現(xiàn),直接使用Character.toChars()方法將unicode編碼轉(zhuǎn)換為一個(gè)char數(shù)組,再將這個(gè)char數(shù)組轉(zhuǎn)換成為字符串就可以直接操作了,系統(tǒng)會(huì)自動(dòng)將其解析為表情圖片,可以直接顯示在textview組件當(dāng)中,不需要我們做任何其他的事情。
代碼實(shí)現(xiàn):
| private?void?setEmojiToTextView() { ????int?unicodeJoy =?0x1F602; ????String emojiString = getEmojiStringByUnicode(unicodeJoy); ????tvTest.setText(emojiString); } ? private?String getEmojiStringByUnicode(int?unicode) { ????return?new?String(Character.toChars(unicode)); } |
然而…………………………….
上面的方法是沒(méi)有做任何特殊處理的,完全是以來(lái)設(shè)備自己的字體庫(kù)來(lái)進(jìn)行?Emoji?渲染的,這就會(huì)導(dǎo)致有一些?Emoji?在某些設(shè)備上顯示不出來(lái)的情況。
Emoji?無(wú)法顯示,會(huì)被顯示成一個(gè)豆腐塊?“?” ,而這并不是我們想要的。如何處理它,這里就必須提到下面這個(gè)EmojiCompat.
三、使用 EmojiCompat(官方庫(kù))
3.1?什么是?EmojiCompat
根據(jù)官方文檔描述,EmojiCompat?支持庫(kù)主要是為了讓?Android?設(shè)備,達(dá)到最新的?Emoji?符號(hào)的顯示效果,它可以防止應(yīng)用中,出現(xiàn)以豆腐塊?“?” 的形式來(lái)顯示?Emoji,雖然它僅僅只是因?yàn)槟惝?dāng)前的設(shè)備沒(méi)有這個(gè)字體而已。通過(guò)?EmojiCompat?,你的設(shè)備無(wú)需等待?Android?系統(tǒng)更新,就可以獲得最新的?Emoji?表情顯示效果。
3.2如何使用 EmojiCompat
EmojiCompat?支持庫(kù),最低支持到?Android 4.4(Api Level 19)?的系統(tǒng)設(shè)備。
EmojiCompat?提供兩種字體的支持方式,它們分別是:
1.可下載的字體配置。(殘廢狀態(tài))
本地捆綁的字體配置。
這兩種使用方式,除了引用的庫(kù)不同之外,最根本的原因在于,可下載的字體的方式,會(huì)在首次啟動(dòng)的時(shí)候檢查本地是否有該字體,沒(méi)有的話會(huì)從網(wǎng)上下載最新的?Emoji?字體;而本地捆綁的方式,會(huì)在?App?打包的過(guò)程中,植入一個(gè)最新的?Emoji?字體文件,然后遇到不能支持的?Emoji,就會(huì)從這個(gè)字體文件中,加載資源并且渲染。
目前官方使用的是?NotoColorEmojiCompat.ttf?字體文件(其實(shí)這里也可以手動(dòng)加載其他的ttf字體文件,操作流程見(jiàn)文后)
本地捆綁的方式會(huì)嵌入一個(gè)字體文件,無(wú)形中增大了?Apk?安裝包的體積,但是可下載字體的方式,又完全依賴?Google?服務(wù),所以在國(guó)內(nèi)基本上是處于殘廢狀態(tài),在這個(gè)大環(huán)境下,我們這里只能選擇本地捆綁的方式來(lái)使用?EmojiCompat。
無(wú)論使用哪種方式配置字體,對(duì)于?EmojiCompat?而言,其實(shí)是不關(guān)心的,它只需要判斷當(dāng)前設(shè)備是否支持這個(gè)?Emoji,支持就使用系統(tǒng)內(nèi)置的,不支持的話,就使用?EmojiSpans?來(lái)替換?CharSequence,來(lái)達(dá)到替換渲染的效果。
EmojiCompat?的運(yùn)行原理如下圖所示。
3.3 本地捆綁的字體配置方式
既然可下載的?Emoji?字體,需要配合?Google?服務(wù),那這里就不再過(guò)多介紹了。
本文主要講解如何使用本地捆綁的方式,使用?EmojiCompat。
第一步,需要添加?Gradle?依賴。
?展開(kāi)源碼
第二步,初始化?EmojiCompat。
初始化?EmojiCompat?,需要兩個(gè)步驟。
首先需要生成一個(gè)?BundledEmojiCompatConfig?對(duì)象,它的構(gòu)造方法接收一個(gè)?Context。
再調(diào)用?EmojiCompat.init()?方法,將前面生成的?config?傳遞給它進(jìn)行初始化。
這個(gè)過(guò)程越早越好,因?yàn)槌跏蓟呛臅r(shí)的,它會(huì)去加載打包的時(shí)候,嵌入的?Emoji?字體文件,所以大概需要消耗?150ms?的時(shí)間,并且占用大概?200kb?的內(nèi)存。
| public?class?MyApplication?extends?Application { @Override ????public?void?onCreate() { ???????super.onCreate(); ???????EmojiCompat.Config config =?new?BundledEmojiCompatConfig(this); ???????EmojiCompat.init(config); ????} } |
第三步,使用?EmojiCompat。
初始化完成之后,就剩下如何使用它了。
EmojiCompat?的處理邏輯,前面已經(jīng)使用圖片描述清楚了。它會(huì)加載一個(gè)?Emoji?字體,然后判斷當(dāng)前設(shè)備是否支持需要顯示的?Emoji,如果不支持,則使用?EmojiSpans?替換它,最終將處理過(guò)的?CharSequence?設(shè)置到?TextView?上。
而這個(gè)過(guò)程,EmojiCompat?提供了非常簡(jiǎn)單的方法,process()。從它的簽名可以看出,它接受一個(gè)?CharSequence?并處理它,然后返回一個(gè)?CharSequence。
舉個(gè)例子:這里轉(zhuǎn)換一個(gè)笑臉的表情。EmojiCompat.get().process("\uD83D\uDE01")
process()?需要接受一個(gè)?Unicode?的字符,所以如果得到的數(shù)據(jù)是前面提到的?Emoji Code?的話,就需要一步單獨(dú)的轉(zhuǎn)換。process()?內(nèi)部已經(jīng)幫我們完成了轉(zhuǎn)換,這些細(xì)節(jié)都無(wú)需我們關(guān)心,我們只需要將它返回的?CharSequence?設(shè)置給?TextView?就可以了。
3.4 Emoji AppCompat Widgets
在實(shí)際項(xiàng)目中,如果每次都需要通過(guò)?EmojiCompat.get().process()?對(duì)字符串進(jìn)行處理,其實(shí)也挺麻煩的。為此?Google?還為開(kāi)發(fā)者提供了對(duì)應(yīng)控件支持。
如果需要使用它,就需要引入新的依賴庫(kù)。
| dependencies { ? ??????compile?"com.android.support:support-emoji-appcompat:$version" ? } |
引入之后,就可以直接在?XML?中使用?EmojiAppCompat?提供的控件。
使用?support-emoji-appcompat?只是節(jié)省了我們?process()?的步驟,但是依然需要?init()?。
3.5 自定義控件支持 Emoji
你可以一直使用?progress()?或者使用?EmojiAppCompatXxx?控件,但是如果你想要自定義一個(gè)控件來(lái)顯示?Emoji,就需要使用?EmojiCompat?提供的另外兩個(gè)幫助類。
EmojiTextViewHelper
EmojiEditViewHelper
這兩個(gè)使用起來(lái)非常簡(jiǎn)單,一個(gè)用于處理純展示的控件,一個(gè)用于處理有輸入的狀態(tài)的控件,非常的簡(jiǎn)潔明了。
哪怕不記得了,看看?EmojiAppCompatTextView?和?EmojiAppCompatEditView?中的實(shí)現(xiàn)方式就可以了。
這里拿?EmojiAppCompatTextView?舉例子,只需要在幾個(gè)關(guān)鍵的位置上,使用?EmojiTextViewHelper?的對(duì)應(yīng)方法即可。
3.6 EmojiCompat面臨的問(wèn)題
整體來(lái)說(shuō)?EmojiCompat?還是很好用的,無(wú)論使用哪種方式加載它,實(shí)際上我們都不需要做過(guò)多的干預(yù)。
這里參考官方文檔,列舉最常見(jiàn)的幾個(gè)問(wèn)題。
1、下載字體的下載策略是怎么樣的?
Emoji?字體在第一次使用的時(shí)候,會(huì)檢測(cè)是否存在于當(dāng)前設(shè)備,如果不存在則在子線程中進(jìn)行下載。
2、初始化需要多長(zhǎng)時(shí)間?
當(dāng)本地已經(jīng)有字體之后,初始化?EmojiCompat?大約需要?150?毫秒。
3、EmojiCompat?支持庫(kù),會(huì)使用多少內(nèi)存?
目前,Emoji?字體被完全加載之后,會(huì)使用大約?200kb?的內(nèi)存。
4、在?Android 4.4?以下的設(shè)備上,使用?EmojiAppCompatXxx?控件會(huì)發(fā)生什么情況?
EmojiCompat?內(nèi)部已經(jīng)做了兼容處理,在低版本上就和使用普通的?AppCompatXxx?控件一樣。
5、本地捆綁的?Emoji?字體文件,大約有多大?
本地捆綁的?Emoji?字體文件?NotoColorEmojiCompat.ttf,會(huì)在打包的時(shí)候嵌入到?assets?目錄下,現(xiàn)在實(shí)際情況來(lái)看大小有?7.4MB,這會(huì)直接造成?Apk?的增大。
更多的細(xì)節(jié),還是建議大家閱讀官方文檔。
https://developer.android.google.cn/guide/topics/ui/look-and-feel/emoji-compat.html
四、EmojiCompat 的缺陷?
在實(shí)際使用?EmojiCompat?的過(guò)程中,還遇到了一個(gè)不能算缺陷的缺陷。
它只有在當(dāng)前設(shè)備遇到不被支持的?Emoji?的時(shí)候,才會(huì)從?Support Font?中加載字體,如果有,它會(huì)使用?System Font?。
這也不能怪?EmojiCompat?的設(shè)計(jì)者,它的出發(fā)點(diǎn),是為了解決?Emoji?在某些設(shè)備中,顯示豆腐塊?“?” 的問(wèn)題,而不關(guān)心它到底是不是顯示最新的?Emoji,是在解決有無(wú)的問(wèn)題。
這就很尷尬了,其實(shí)有時(shí)候?Android?設(shè)備內(nèi)置支持的字體,顯示的效果并不好,我們先來(lái)看看使用?EmojiCompat?前后的對(duì)比效果。
很清晰的可以看到?EmojiCompat?幫我補(bǔ)齊了我當(dāng)前設(shè)備部支持的那些?Emoji?表情,但是并沒(méi)有將?Android?的果凍表情替換為標(biāo)準(zhǔn)的?Emoji?表情。
那么,如果我們想要讓它顯示最新的?Emoji?,我們需要這么辦呢?
前面提到,自從?Emoji?開(kāi)始被標(biāo)準(zhǔn)化之后,其實(shí)就是一個(gè)字體,并且?EmojiCompat?也是幫我們捆綁嵌入了一個(gè)字體包在?assets?目錄下,那我們只需要讓我們顯示的?TextView?加載這個(gè)?Emoji?字體,就可以解決這個(gè)問(wèn)題。
五、項(xiàng)目定制化顏文字應(yīng)用舉例
按“設(shè)置鍵”編輯,這里面的“設(shè)置鍵”就是圖標(biāo)的形式展示的,但是和我們正常開(kāi)發(fā)中使用的圖標(biāo)不一樣,UX并沒(méi)有給我們提供任何的圖片素材,不需要我們將圖片實(shí)體打進(jìn)我們的apk包中。顏文字實(shí)際上就是一套預(yù)制的編碼規(guī)范,將Unicode編碼對(duì)應(yīng)一套圖標(biāo)展示,
注意到了關(guān)鍵點(diǎn),“預(yù)制的編碼規(guī)范”,emm~~局限性太大,太依賴系統(tǒng)和編碼規(guī)范了(定制化系統(tǒng))?
目前顏文字的實(shí)現(xiàn)的方式主要有兩種大致可以分為兩類:
系統(tǒng)支持的Emoji圖標(biāo)
自定義Emoji圖標(biāo)
這是目前Github上使用最廣泛的emoji開(kāi)源表情庫(kù):https://github.com/rockerhieu/emojicon
做法上,實(shí)質(zhì)是用富文本去替換代碼中的Unicode從而達(dá)到圖文混排的效果,從表現(xiàn)效果上看,就是顏文字。(富文本做圖文混排后續(xù)補(bǔ)充)
六、Emojicon數(shù)據(jù)庫(kù)中的存取問(wèn)題
Emojicon表情在數(shù)據(jù)庫(kù)中的存取方法在使用過(guò)程中出現(xiàn)了問(wèn)題,出現(xiàn)了表情存到數(shù)據(jù)庫(kù)之后變?yōu)榭瞻?#xff0c;取出后也是空白的問(wèn)題。
emoji分為?softbank emoji?和?unicode emoji,由于目前?softbank emoji?已停止更新,所以大多數(shù)?emoji?為?unicode emoji,emojicon?也是如此。unicode emoji?是四個(gè)字節(jié)長(zhǎng)度,格式類似于?\uD83D?之類。由于項(xiàng)目和數(shù)據(jù)庫(kù)都是UTF-8編碼,UTF-8?是變長(zhǎng)編碼,可能是2-4個(gè)字節(jié),而?MySQL?數(shù)據(jù)庫(kù)的普通?UTF-8?編碼只有三個(gè)字節(jié),所以會(huì)出現(xiàn)無(wú)法解析的情況。
解決方案大致有以下幾種方法解決:
1.更改數(shù)據(jù)庫(kù)編碼
??MySQL?版本?5.5.3?以上可以使用utf8mb4編碼來(lái)進(jìn)行存儲(chǔ),此編碼支持4字節(jié)的?UTF-8?字符。但是這樣做很可能會(huì)在其他地方出現(xiàn)不兼容的問(wèn)題,且更改數(shù)據(jù)庫(kù)編碼對(duì)系統(tǒng)整體改動(dòng)太大,不推薦使用。
2.轉(zhuǎn)化為三個(gè)字節(jié)的?softbank emoji
??如果要轉(zhuǎn)化為?softbank emoji?的話,需要通過(guò)對(duì)照表將?unicode emoji?轉(zhuǎn)化為?softbank emoji,工作量不小,而且新的表情并不支持,不推薦使用。
3.對(duì)?unicode?字符串進(jìn)行加密解密
??采用了?Apache?的?commons-lang?(見(jiàn)附件二)包中的?StringEscapeUtils?類來(lái)對(duì)字符串進(jìn)行加密解密:
//加密
mContent = StringEscapeUtils.escapeJava(emojiEditText.getText().toString());
//解密
mComment.setContent(StringEscapeUtils.unescapeJava(json.getJSONObject(i).getString("content")));
?
?
附一:替換手機(jī)emoji表情庫(kù)操作流程(需要root權(quán)限):
方式一:通過(guò)adb命令替換
adb root
adb remount
//push文件到?system/fonts
adb push C:\Users\jjj\Desktop\emojittf\ios12\NotoColorEmoji.ttf? system/fonts
//修改權(quán)限
adb shell chmod 644 /system/fonts/NotoColorEmoji.ttf
//同步
adb shell sync
//最后重啟一下設(shè)備
adb reboot
?
方式二:手動(dòng)替換ttf字體文件
手機(jī)已經(jīng)root,下載ES文件夾,進(jìn)入根目錄,找到/system/fonts,用需要的NotoColorEmoji.ttf替換掉之前的就行。
?
?
附:各版本NotoColorEmoji.ttf文件
ios12
https://download.csdn.net/download/geniushorse/11329664
ios11
https://download.csdn.net/download/geniushorse/11329683
ios10
https://download.csdn.net/download/geniushorse/11329687
android 9.0
https://download.csdn.net/download/geniushorse/11329693
android 8.0
https://download.csdn.net/download/geniushorse/11329698
?
附件二:commons-lang3-3.11.jar(阿帕奇的一個(gè)通用包)
?
總結(jié)
以上是生活随笔為你收集整理的浅谈emoji(分析与使用)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 国内B端竞品调研网站一网打尽
- 下一篇: web 文字描边动画