Android 官方兼容庫(kù) EmojiCompat Support Library

什么是 emoji铐然?

emoji 是一種 表情符號(hào)晌缘,來(lái)自日語(yǔ)詞匯“絵文字”(假名為“えもじ”纠永,讀音即 emoji)

它的創(chuàng)造者是日本人栗田穰崇 ( Shigetaka Kurita ) 领跛,他將目光投向兒時(shí)的各種元素以獲取靈感,如日本漫畫(huà)和日本漢字等叔收〕菟耄“日本漫畫(huà)中有許多不同的符號(hào)。漫畫(huà)家會(huì)畫(huà)出一些表情饺律,表現(xiàn)一個(gè)人滿頭大汗或是迸發(fā)出一個(gè)想法時(shí)頭上出現(xiàn)一個(gè)燈泡窃页。”同時(shí)复濒,從日本漢字中他獲得了一種能力脖卖,用簡(jiǎn)單的字符來(lái)表達(dá)“秘密”和“愛(ài)”等抽象概念。

image.png

早期的 emoji 表情并沒(méi)有一套統(tǒng)一的規(guī)范芝薇,日本的三大電信運(yùn)營(yíng)商胚嘲,NTT DoCoMo作儿,au/KDDI洛二,Softbank 都各自有一套關(guān)于 Emoji 的編碼規(guī)范,導(dǎo)致運(yùn)營(yíng)商用戶之間發(fā)送 emoji 表情時(shí)無(wú)法顯示攻锰。

直到2010年10月晾嘶,隨著 Unicode6.0 的發(fā)布,Emoji 的編碼以及對(duì)應(yīng)的表情圖片正式被規(guī)范化娶吞,核心 Emoji 表情包含722個(gè) Emoji 編碼垒迂。

之后 2014年6月15日發(fā)布的 Unicode 7.0 規(guī)范以及 2016年6月22日發(fā)布的 Unicode 9 規(guī)范都不斷地加入新的 emoji 表情,目前整個(gè) emoji 表情已經(jīng)達(dá)到了一千多個(gè)妒蛇。

感興趣的同學(xué)可以到這里查看所有表情對(duì)應(yīng)的編碼

emoji 表情列表


Android 對(duì) emoji 表情的兼容

很多同學(xué)可能并沒(méi)有注意到 Android 設(shè)備上的 Emoji 表情

一般情況下机断,我們?cè)谑謾C(jī)上進(jìn)行操作時(shí)楷拳, 只有使用了輸入法自帶的表情及 emoji 表情才會(huì)在文本中產(chǎn)生 emoji 編碼。

image.png
image.png

在 Android 4.4 之前吏奸, Android 并不支持 emoji 表情欢揖,當(dāng)時(shí)的解決方案主要是通過(guò) imageSpan 配合 spannableString,來(lái)替換掉文字中的 emoji unicode 編碼符號(hào)奋蔚。

從 Android 4.4 開(kāi)始她混, 官方開(kāi)始了 emoji 表情的支持,實(shí)現(xiàn)原理基本就是通過(guò)把 emoji 表情內(nèi)置在系統(tǒng)的 ttf 字體庫(kù)中泊碑,對(duì)文本進(jìn)行過(guò)濾后顯示出 emoji 表情坤按。

由于不同 Android 版本內(nèi)置的 ttf 字體庫(kù)對(duì) emoji 表情的版本支持程度不同,導(dǎo)致老版本的 Android 對(duì)最新的 emoji 表情支持不全馒过,所以一些 在新的 unicode 版本規(guī)范中被加入的 emoji 表情在老的 Android 設(shè)備上會(huì)顯示方框亂碼臭脓。

為了處理這個(gè)問(wèn)題,除去上文提到的 spannable 的處理方案腹忽,我們還可以通過(guò)定義自己的 ttf 字體庫(kù)給文本空間指定字體來(lái)顯示 emoji 表情谢鹊。


EmojiCompat Support Library 的誕生

正是由于上文提到的兼容問(wèn)題,Google 官方的 EmojiCompat Support Library 誕生了留凭。

目前這個(gè)庫(kù)能向下兼容到 Android 4.4佃扼,其主要目標(biāo)就是為了讓我們的 Android 設(shè)備能夠支持最新的 emoji 表情,防止最新的 emoji 表情在我們的手機(jī)上顯示為?蔼夜。

Emoji 對(duì)照

EmojiCompat 通過(guò) CharSequence 文本中的 emoji 對(duì)應(yīng)的 unicode 編碼來(lái)識(shí)別 emoji 表情兼耀,將他們替換成 EmojiSpans ,最后再將 EmojiSpan 渲染成對(duì)應(yīng)的 emoji 表情符號(hào)求冷。

emojiCompat處理過(guò)程

對(duì)于 EmojiCompat 的使用瘤运,有兩種配置方式:

Downloadable fonts configuration

Downloadable fonts 是 Android O 新增的一個(gè)功能,支持通過(guò) google mobile service 遠(yuǎn)程拉取需要的字體庫(kù)到本地來(lái)進(jìn)行使用匠题。

由于國(guó)內(nèi)屏蔽了 Google Service 拯坟,所以這種方式在國(guó)內(nèi)我們使用不了,這里我們就不做詳細(xì)介紹了韭山。

Bundled fonts configuration

Bundled fonts 即打包字體郁季,就是使用本地打包好的 emoji 字體庫(kù)來(lái)兼容 emoji 表情。

目前官方使用的是 NotoColorEmojiCompat.ttf 字體文件钱磅。


EmojiCompat 的使用

接下來(lái)我們來(lái)看看如何使用 emojiCompat 庫(kù)

添加依賴庫(kù)

首先我們?cè)?build.gradle 中配置我們的依賴包梦裂,由于我們使用的是 Bundled fonts 的配置,所以我們需要先引入我們的 emoji bundle 庫(kù):

dependencies {
    ...
    compile "com.android.support:support-emoji-bundled:$version"
}

這里我 $version 設(shè)置的版本是 26.0.0-beta1盖淡,如果編譯過(guò)程中提示找不到依賴庫(kù)年柠,需要在 repositories 倉(cāng)庫(kù)配置中加入 Google 的 maven 地址:

allprojects {
    repositories {
        jcenter()
        maven { url 'https://maven.google.com' }
    }
}

接著我們引入 EmojiCompat 的組件庫(kù):

dependencies {
    ...
    compile "com.android.support:support-emoji:26.0.0-beta1"
}

該組件庫(kù)對(duì)應(yīng)的 emojiCompat 組件:

<android.support.text.emoji.widget.EmojiTextView
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"/>

<android.support.text.emoji.widget.EmojiEditText
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"/>

<android.support.text.emoji.widget.EmojiButton
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"/>

如果你使用的是 AppCompat 庫(kù), 也可以直接添加 emojiCompat 的 compat 組件庫(kù)

dependencies {
      compile "com.android.support:support-emoji-appcompat:26.0.0-beta1"
}

該引用庫(kù)對(duì)應(yīng)的組件:

<android.support.text.emoji.widget.EmojiAppCompatTextView
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"/>

<android.support.text.emoji.widget.EmojiAppCompatEditText
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"/>

<android.support.text.emoji.widget.EmojiAppCompatButton
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"/>

compat 庫(kù)跟非 compat 庫(kù)之間的差別主要就是在使用的組件名稱上褪迟,其他的方式基本一致冗恨。

初始化 EmojiCompat

在正式使用 EmojiCompat 之前我們還需要對(duì)其進(jìn)行初始化

public class MyApplication extends Application {
@Override
    public void onCreate() {
       super.onCreate();
       EmojiCompat.Config config = new BundledEmojiCompatConfig(this);
       EmojiCompat.init(config);
    }
}

此時(shí)我們便可以使用上一步添加的 emojiCompat 組件來(lái)替換原有的 TextView答憔、 EditText 以及 Button 組件了,當(dāng)文本中遇到對(duì)應(yīng)的 emoji 表情編碼時(shí)就會(huì)自動(dòng)替換為 emoji 表情了掀抹。


device-2017-06-30-134851.png

不通過(guò)組件使用 emojiCompat 兼容庫(kù)

EmojiCompat 庫(kù)通過(guò) EmojiSpan 來(lái)渲染正確的表情圖片攀唯,因此需要先將文本 CharSequence 根據(jù) emoji 編碼轉(zhuǎn)換成對(duì)應(yīng)的 EmojiSpan Spanned 實(shí)例。

EmojiCompat 專門提供了一個(gè) process() 方法用于CHarSequence 實(shí)例的轉(zhuǎn)換

使用這種方法渴丸,我們可以緩存處理過(guò)的實(shí)例而不是原始字符串侯嘀,在需要使用的地方直接調(diào)用該實(shí)例,從而提高應(yīng)用程序的性能谱轨。

TextView regularTextView = findViewById(R.id.regular_text_view);

CharSequence processed = EmojiCompat.get().process("neutral face \uD83D\uDE10");

regularTextView.setText(processed);

自定義 EmojiCompat 組件

除了上面提到的通過(guò) EmojiCompat 的 process 方法轉(zhuǎn)換 spanned 實(shí)例外戒幔,我們還可以通過(guò)官方提供的兩個(gè) widget helper 類來(lái)自定義我們的 TextView 以及 EditTextView 組件:

android.support.text.emoji.widget.EmojiTextViewHelper
android.support.text.emoji.widget.EmojiEditTextHelper

示例代碼:

自定義Emoji TextView

public class MyTextView extends AppCompatTextView {
   ...
   public MyTextView(Context context) {
       super(context);
       init();
   }
   ...
   private void init() {
       getEmojiTextViewHelper().updateTransformationMethod();
   }

   @Override
   public void setFilters(InputFilter[] filters) {
       super.setFilters(getEmojiTextViewHelper().getFilters(filters));
   }

   @Override
   public void setAllCaps(boolean allCaps) {
       super.setAllCaps(allCaps);
       getEmojiTextViewHelper().setAllCaps(allCaps);
   }

   private EmojiTextViewHelper getEmojiTextViewHelper() {
       ...
   }
}

自定義 Emoji EditText

public class MyEditText extends AppCompatEditText {
   ...
   public MyEditText(Context context) {
       super(context);
       init();
   }
   ...
   private void init() {
       super.setKeyListener(getEmojiEditTextHelper().getKeyListener(getKeyListener()));
   }

   @Override
   public void setKeyListener(android.text.method.KeyListener keyListener) {
       super.setKeyListener(getEmojiEditTextHelper().getKeyListener(keyListener));
   }

   @Override
   public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
       InputConnection inputConnection = super.onCreateInputConnection(outAttrs);
       return getEmojiEditTextHelper().onCreateInputConnection(inputConnection, outAttrs);
   }

   private EmojiEditTextHelper getEmojiEditTextHelper() {
       ...
   }
}

總結(jié)

看了上面的使用步驟,EmojiCompat 的使用是不是很方便呢土童?

目前來(lái)說(shuō)诗茎,EmojiCompat 只兼容 Android 4.4 以上的設(shè)備,對(duì)于 4.4 以下的設(shè)備献汗,它的行為跟普通的 Android 組件沒(méi)有差異敢订。

EmojiCompat 的初始化時(shí)間大約只需要 150 毫秒,內(nèi)存的占用大概在200kb罢吃,所以你可以放心大膽地去使用它楚午。

這里是官方的 Demo 地址:
https://github.com/googlesamples/android-EmojiCompat

里面包含了 downloadable fonts 的使用,因?yàn)楸容^完善 尿招,所以就不放我自己的 Demo 啦矾柜,感興趣的小伙伴趕緊去下載看看吧!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末就谜,一起剝皮案震驚了整個(gè)濱河市怪蔑,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌丧荐,老刑警劉巖缆瓣,帶你破解...
    沈念sama閱讀 206,482評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異虹统,居然都是意外死亡弓坞,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,377評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門窟却,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)昼丑,“玉大人,你說(shuō)我怎么就攤上這事夸赫。” “怎么了咖城?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,762評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵茬腿,是天一觀的道長(zhǎng)呼奢。 經(jīng)常有香客問(wèn)我,道長(zhǎng)切平,這世上最難降的妖魔是什么握础? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,273評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮悴品,結(jié)果婚禮上禀综,老公的妹妹穿的比我還像新娘。我一直安慰自己苔严,他們只是感情好定枷,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,289評(píng)論 5 373
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著届氢,像睡著了一般欠窒。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上退子,一...
    開(kāi)封第一講書(shū)人閱讀 49,046評(píng)論 1 285
  • 那天岖妄,我揣著相機(jī)與錄音,去河邊找鬼寂祥。 笑死荐虐,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的丸凭。 我是一名探鬼主播缚俏,決...
    沈念sama閱讀 38,351評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼贮乳!你這毒婦竟也來(lái)了忧换?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 36,988評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤向拆,失蹤者是張志新(化名)和其女友劉穎亚茬,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體浓恳,經(jīng)...
    沈念sama閱讀 43,476評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡刹缝,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,948評(píng)論 2 324
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了颈将。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片梢夯。...
    茶點(diǎn)故事閱讀 38,064評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖晴圾,靈堂內(nèi)的尸體忽然破棺而出颂砸,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 33,712評(píng)論 4 323
  • 正文 年R本政府宣布人乓,位于F島的核電站勤篮,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏色罚。R本人自食惡果不足惜碰缔,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,261評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望戳护。 院中可真熱鬧金抡,春花似錦、人聲如沸腌且。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,264評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)切蟋。三九已至统捶,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間柄粹,已是汗流浹背喘鸟。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,486評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留驻右,地道東北人什黑。 一個(gè)月前我還...
    沈念sama閱讀 45,511評(píng)論 2 354
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像堪夭,于是被迫代替她去往敵國(guó)和親愕把。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,802評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容