Android輸入法開發(fā)

  • 輸入法編輯器(IME)是一個便于用戶輸入文本的控件膜眠。Android提供了一個可擴(kuò)展的輸入法框架籽孙,允許應(yīng)用程序提供可替代的輸入法会钝,比如屏幕上的鍵盤或者語音輸入伐蒋。在安裝輸入法后,用戶可以通過系統(tǒng)選項選擇想要使用的輸入法迁酸。
  • 想要添加一個輸入法先鱼,你需要創(chuàng)建一個Android應(yīng)用并包含一個繼承自InputMethodService的類。此外奸鬓,同城創(chuàng)建一個設(shè)置頁面來承載輸入發(fā)的各個選項焙畔。你可以自行定義一個設(shè)置的UI。

下面講述以下幾個內(nèi)容:

  • 輸入法的生命周期
  • 在應(yīng)用的清單文件中定義輸入法組件
  • 輸入法相關(guān)接口
  • 設(shè)計一個款輸入法的UI
  • 發(fā)送文本到應(yīng)用
  • 輸入法子類型的使用

一串远、輸入法的生命周期

輸入法的生命周期如下圖所示:

20170206170754535.png

二宏多、在清單文件中定義輸入法組件

在Android系統(tǒng)中儿惫,IME是一個包含特殊IME服務(wù)的應(yīng)用程序。應(yīng)用的清單文件必須聲明輸入法服務(wù)伸但,請求必須的權(quán)限肾请,提供一個intent filter來匹配 action.view.InputMethod,并提供定義了IME特征的元數(shù)據(jù)(metadata)更胖。此外铛铁,可以定義一個設(shè)置頁面來提供用戶修改IME配置的接口,它可以被系統(tǒng)設(shè)置所啟動函喉。

  • 下面的代碼片段聲明了一個IME服務(wù)避归。請求了 BIND_INPUT_METHOD 權(quán)限來允許服務(wù)連接到系統(tǒng)的IME荣月,建立intent filter和metadata:
<!-- Declares the input method service -->
    <service android:name="FastInputIME"
        android:label="@string/fast_input_label"
        android:permission="android.permission.BIND_INPUT_METHOD">
        <intent-filter>
            <action android:name="android.view.InputMethod" />
        </intent-filter>
        <meta-data android:name="android.view.im"
android:resource="@xml/method" />
    </service>

下面的代碼片段聲明了IME的設(shè)置頁面管呵,它擁有 ACTION_MAIN 的intent filter來表示它是IME程序的主入口

<!-- Optional: an activity for controlling the IME settings -->
    <activity android:name="FastInputIMESettings"
        android:label="@string/fast_input_settings">
        <intent-filter>
            <action android:name="android.intent.action.MAIN"/>
        </intent-filter>
    </activity>

也可以從IME的UI提供直接進(jìn)入設(shè)置的入口。

三哺窄、輸入法API

與IME相關(guān)的類在 android.inputmethodserviceandroid.view.inputmethod 包中捐下。KeyEvent 類對于處理鍵盤特征至關(guān)重要。
IME的核心部分是一個服務(wù)組件萌业,即一個繼承自InputMethodService的類坷襟。此外為了實現(xiàn)一般服務(wù)的生命周期,這個類提供了IME的UI生年,處理用戶輸入和傳輸文本到指定區(qū)域以及當(dāng)前焦點的回調(diào)婴程。InputMethodService類提供了絕大多數(shù)管理IME狀態(tài)和與當(dāng)前輸入?yún)^(qū)域交互的實現(xiàn)。

下面幾個類也很重要抱婉。
BaseInputConnection
定義了輸入法和應(yīng)用之間接收輸入的交互通道档叔。使用它來讀取光標(biāo)周圍的文本,提交文本到輸入框以及發(fā)送鍵盤事件給應(yīng)用蒸绩。應(yīng)用應(yīng)該集成此類衙四。

KeyboardView
一個View的擴(kuò)展,描繪了一個鍵盤和用戶輸入事件的響應(yīng)患亿。鍵盤的布局是被Keyboard的實例指定传蹈,可以定義一個XML文件。

四步藕、設(shè)計輸入法UI

IME有兩個主要的視覺元素:即輸入視圖和備選視圖惦界。你只需要實現(xiàn)和你設(shè)計的輸入法有關(guān)的元素。

4.1 輸入視圖

輸入視圖是用戶使用按鍵咙冗,手寫或者手勢在表單中輸入文本的UI沾歪。
當(dāng)IME第一次顯示,系統(tǒng)會調(diào)用 onCreateInputView() 回調(diào)乞娄。在你實現(xiàn)的這個方法中瞬逊,你創(chuàng)建你想要的IME窗口的布局并返回給系統(tǒng)显歧。下面片段是一個例子:

@Override
    public View onCreateInputView() {
        MyKeyboardView inputView =
            (MyKeyboardView) getLayoutInflater().inflate( R.layout.input, null);

        inputView.setOnKeyboardActionListener(this);
inputView.setKeyboard(mLatinKeyboard);

        return mInputView;
    }

這里的MyKeyboardView是一個自定義的實現(xiàn)了 KeyboardView 的實例,如果你構(gòu)建的是一個傳統(tǒng)的QWERTY鍵盤确镊,請查看 KeyboardView 類士骤。

4.2.候選視圖

候選視圖是供用戶選擇可選詞和推薦詞的視圖。在IME的生命周期中蕾域,系統(tǒng)在準(zhǔn)備好顯示備選視圖的時候會調(diào)用onCreateCandidatesView()拷肌。在你實現(xiàn)的這個方法中,返回顯示詞匯建議的布局旨巷,當(dāng)什么都不顯示時巨缘,返回null。
若要查看實現(xiàn)用戶建議詞匯的例子采呐,請查看SoftKeyboard示例應(yīng)用若锁。

4.3.UI設(shè)計依據(jù)

此部分介紹了一些IME的UI設(shè)計思想。

· 應(yīng)對多元化的屏幕尺寸
你的IME的UI必須可以適配不同屏幕的尺寸斧吐,且必須處理豎屏和橫屏兩種方向又固。在非全屏模式下,為應(yīng)用程序留出足夠的空間以顯示文本字段和任何相關(guān)聯(lián)的上下文煤率,使得IME不會占用屏幕一半以上的空間仰冠。在全屏模式下沒有這個問題。

· 處理不同的輸入類型
Android的輸入框允許你選擇一個特殊的輸入類型蝶糯,比如自由文本洋只,數(shù)字,網(wǎng)址昼捍,郵箱地址识虚,收索內(nèi)容等。當(dāng)你實現(xiàn)一個新的IME端三,您需要檢測每個字段的輸入類型舷礼,并為其提供適當(dāng)?shù)慕涌凇?/strong>但是,你不必設(shè)置IME以檢查用戶輸入的文本對輸入類型有效; 這是擁有文本字段的應(yīng)用程序的責(zé)任郊闯。

當(dāng)輸入字段接收焦點并且您的IME啟動時妻献,系統(tǒng)調(diào)用 onStartInputView(),傳遞一個 EditorInfo 對象团赁,該對象包含有關(guān)文本字段的輸入類型和其他屬性的詳細(xì)信息育拨。 在此對象中,inputType 字段包含文本字段的輸入類型欢摄。
輸入類型字段是一個包含用于各種輸入類型設(shè)置的位模式的int參數(shù)熬丧。 要測試它的文本字段的輸入類型,用常量TYPE_MASK_CLASS屏蔽它怀挠,像這樣:
inputType & InputType.TYPE_MASK_CLASS
輸入類型位模式可以具有幾個值中的一個析蝴,包括:
TYPE_CLASS_NUMBER
用于輸入數(shù)字的文本字段害捕。
TYPE_CLASS_DATETIME
用于輸入日期和時間的文本字段。
TYPE_CLASS_PHONE
用于輸入電話號碼的文本字段闷畸。
TYPE_CLASS_TEXT
用于輸入所有支持的字符的文本字段尝盼。

這些常量在 InputType 的參考文檔中有更詳細(xì)的描述。
inputType字段可以包含指示文本字段類型的其他位佑菩,例如:
TYPE_TEXT_VARIATION_PASSWORD
用于輸入密碼的TYPE_CLASS_TEXT 的變體盾沫。 輸入法將顯示標(biāo)記,而不是實際文本殿漠。
TYPE_TEXT_VARIATION_URI
用于輸入網(wǎng)址和其他統(tǒng)一資源標(biāo)識符(URI)的TYPE_CLASS_TEXT 的變體赴精。
TYPE_TEXT_FLAG_AUTO_COMPLETE
TYPE_CLASS_TEXT 的變體,用于輸入應(yīng)用程序從字典绞幌,搜索或其他工具中“自動完成”的文本蕾哟。
記住在測試這些變量時,用適當(dāng)?shù)某?shù)掩蔽輸入類型啊奄。 可用的掩碼常數(shù)在輸入類型的參考文檔中列出渐苏。
注意:在您自己的IME中掀潮,確保在將其發(fā)送到密碼字段時正確處理文本菇夸。 在輸入視圖和候選視圖中的用戶界面中隱藏密碼。 還要記住仪吧,您不應(yīng)該在設(shè)備上存儲密碼庄新。 要了解更多信息,請參閱“為安全性設(shè)計”指南薯鼠。

五择诈、向應(yīng)用程序發(fā)送文本

當(dāng)用戶使用IME輸入文本時,您可以通過發(fā)送單個鍵事件或在應(yīng)用程序的文本字段中編輯光標(biāo)周圍的文本來向應(yīng)用程序發(fā)送文本出皇。 在任一情況下羞芍,您都使用 InputConnection的實例來傳遞文本。 要獲取此實例郊艘,請調(diào)用 InputMethodService.getCurrentInputConnection() 荷科。

5.1.編輯光標(biāo)周圍的文本

當(dāng)處理文本字段中現(xiàn)有文本的編輯時,BaseInputConnection 中一些更有用的方法是:
getTextBeforeCursor()
返回包含當(dāng)前光標(biāo)位置之前的請求字符數(shù)的 CharSequence 纱注。
getTextAfterCursor()
返回包含當(dāng)前光標(biāo)位置后的請求字符數(shù)的 CharSequence 畏浆。
deleteSurroundingText()
刪除當(dāng)前光標(biāo)位置前后的指定數(shù)量的字符。
commitText()
向文本字段提交 CharSequence 并設(shè)置新的光標(biāo)位置狞贱。

例如刻获,以下代碼段顯示如何使用文本“Hello!”替換光標(biāo)左側(cè)的四個字符:

InputConnection ic = getCurrentInputConnection();

    ic.deleteSurroundingText(4, 0);

    ic.commitText("Hello", 1);

    ic.commitText("!", 1);

5.2.在提交之前撰寫文本

如果您的IME執(zhí)行文本預(yù)測或需要多個步驟來組成字形或單詞瞎嬉,則可以在文本字段中顯示進(jìn)度蝎毡,直到用戶提交單詞厚柳,然后您可以用完成的文本替換部分組合。 當(dāng)你傳遞給 setComposingText()時沐兵,你可以通過添加一個“span”來對文本進(jìn)行特殊處理草娜。
以下代碼段顯示了如何在文本字段中顯示進(jìn)度

2.在提交之前撰寫文本 
如果您的IME執(zhí)行文本預(yù)測或需要多個步驟來組成字形或單詞,則可以在文本字段中顯示進(jìn)度痒筒,直到用戶提交單詞宰闰,然后您可以用完成的文本替換部分組合。 當(dāng)你傳遞給 setComposingText()時簿透,你可以通過添加一個“span”來對文本進(jìn)行特殊處理移袍。 
以下代碼段顯示了如何在文本字段中顯示進(jìn)度

以下屏幕截圖顯示了用戶看到的頁面:


WX20181023-195324@2x.png

5.3.攔截硬件按鍵事件

即使輸入法窗口沒有明確的焦點,它首先接收硬件鍵事件老充,并且可以選擇使用它們或?qū)⑺鼈冝D(zhuǎn)發(fā)到應(yīng)用程序葡盗。 例如,您可能想要使用方向鍵在UI中導(dǎo)航以在組合期間選擇候選項啡浊。 您可能還想捕獲返回鍵以關(guān)閉源自輸入法窗口的任何彈出窗口觅够。
要攔截硬件鍵,重寫onKeyDown()和 onKeyUp()巷嚣。 請參閱 SoftKeyboard 示例應(yīng)用程序的示例喘先。
記住要為你不想處理的鍵調(diào)用super()方法。

六廷粒、創(chuàng)建IME子類型

子類型允許IME公開IME支持的多種輸入模式和語言窘拯。 子類型可以表示:
· 區(qū)域設(shè)置,如en_US或fr_FR
· 輸入模式坝茎,如語音涤姊,鍵盤或手寫
· IME特有的其他輸入樣式,表單或?qū)傩脏头牛?0鍵或qwerty鍵盤布局思喊。

基本上,模式可以是諸如“鍵盤”次酌,“語音”等的任何文本恨课。 子類型還可以暴露這些的組合。
子類型信息用于IME切換器對話框和措,該對話框可從通知欄和IME設(shè)置中使用庄呈。 該信息還允許框架直接引出IME的特定子類型。 當(dāng)構(gòu)建IME時派阱,使用子類型工具诬留,因為它有助于用戶識別和在不同的IME語言和模式之間切換。

您可以使用元素在輸入法的XML資源文件之一中定義子類型。 以下代碼段定義了一個具有兩個子類型的IME:美國英語語言環(huán)境的鍵盤子類型文兑,法國的法語語言環(huán)境的另一個鍵盤子類型

<input-method xmlns:android="http://schemas.android.com/apk/res/android"
        android:settingsActivity="com.example.softkeyboard.Settings"
        android:icon="@drawable/ime_icon"
    <subtype android:name="@string/display_name_english_keyboard_ime"
            android:icon="@drawable/subtype_icon_english_keyboard_ime"
            android:imeSubtypeLanguage="en_US"
            android:imeSubtypeMode="keyboard"
            android:imeSubtypeExtraValue="somePrivateOption=true"
    />
    <subtype android:name="@string/display_name_french_keyboard_ime"
            android:icon="@drawable/subtype_icon_french_keyboard_ime"
            android:imeSubtypeLanguage="fr_FR"
            android:imeSubtypeMode="keyboard"
            android:imeSubtypeExtraValue="foobar=30,someInternalOption=false"
    />
    <subtype android:name="@string/display_name_german_keyboard_ime"
            ...
    />
/>

6.1.從通知欄中選擇TIME子類型

Android系統(tǒng)管理所有IME公開的所有子類型盒刚。 IME子類型被視為它們所屬的IME的模式。 在通知欄中绿贞,用戶可以為當(dāng)前設(shè)置的IME選擇可用的子類型因块,如以下屏幕截圖所示:


20170206171319355.png

20170206171330099.png

6.2.從系統(tǒng)設(shè)置選擇IME子類型

用戶可以在“系統(tǒng)設(shè)置”區(qū)域的“語言和輸入”設(shè)置面板中控制子類型的使用方式。 在 SoftKeyboard 示例應(yīng)用程序中籍铁,文件InputMethodSettingsFragment.java包含一個在IME設(shè)置中實現(xiàn)子類型啟用程序的實現(xiàn)涡上。 有關(guān)如何在IME中支持輸入法子類型的更多信息,請參閱Android SDK中的 SoftKeyboard 示例應(yīng)用程序拒名。


20170206171422115.png

6.3.在IME子類型之間切換

您可以允許用戶通過提供切換鍵(如球形語言圖標(biāo))作為鍵盤的一部分吩愧,在多個IME子類型之間輕松切換。 這樣做大大提高了鍵盤的可用性增显,并可以幫助避免用戶的失望雁佳。 要啟用此類切換,請執(zhí)行以下步驟:
(1). 在輸入法的XML資源文件中聲明 supportsSwitchingToNextInputMethod = “true” 同云。 您的聲明應(yīng)類似于以下代碼段:

<input-method xmlns:android="http://schemas.android.com/apk/res/android"
        android:settingsActivity="com.example.softkeyboard.Settings"
        android:icon="@drawable/ime_icon"
        android:supportsSwitchingToNextInputMethod="true">

(2). 調(diào)用 shouldOfferSwitchingToNextInputMethod() 方法糖权。
(3). 如果方法返回true,則顯示切換鍵炸站。
(4). 當(dāng)用戶點擊切換鍵時星澳,調(diào)用 switchToNextInputMethod(),將false傳遞給第二個參數(shù)武契。 值false表示系統(tǒng)平等對待所有子類型募判,而不管它們屬于什么IME。 指定true要求系統(tǒng)在當(dāng)前IME中循環(huán)遍歷子類型咒唆。

注意:在Android 5.0(API級別21)之前,switchToNextInputMethod()不知道 supportsSwitchingToNextInputMethod 屬性释液。 如果用戶切換到IME而沒有切換鍵全释,他可能會卡在該IME中,無法輕松地切換出來误债。

七浸船、一般IME注意事項

以下是您實現(xiàn)IME時需要考慮的其他事項:
· 為用戶提供一種直接從IME的UI設(shè)置選項的方法。
· 因為設(shè)備上可以安裝多個IME寝蹈,所以提供了用于用戶從輸入法UI直接切換到不同的IME的方式李命。
· 快速啟動IME的UI。根據(jù)需要預(yù)加載或加載任何大型資源箫老,以便用戶在點擊文本字段時看到IME封字。緩存資源和視圖,用于后續(xù)調(diào)用輸入法。
· 相反阔籽,您應(yīng)該在隱藏輸入法窗口后立即釋放大量內(nèi)存分配流妻,以便應(yīng)用程序可以有足夠的內(nèi)存來運行。如果IME處于隱藏狀態(tài)幾秒鐘笆制,請考慮使用延遲消息來釋放資源绅这。
· 請確保用戶可以為與IME關(guān)聯(lián)的語言或區(qū)域設(shè)置輸入盡可能多的字符。請記住在辆,用戶可以在密碼或用戶名中使用標(biāo)點符號证薇,因此您的IME必須提供許多不同的字符,以允許用戶輸入密碼并訪問設(shè)備匆篓。

參考

Android輸入法開發(fā)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末棕叫,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子奕删,更是在濱河造成了極大的恐慌俺泣,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,270評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件完残,死亡現(xiàn)場離奇詭異伏钠,居然都是意外死亡,警方通過查閱死者的電腦和手機谨设,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,489評論 3 395
  • 文/潘曉璐 我一進(jìn)店門熟掂,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人扎拣,你說我怎么就攤上這事赴肚。” “怎么了二蓝?”我有些...
    開封第一講書人閱讀 165,630評論 0 356
  • 文/不壞的土叔 我叫張陵誉券,是天一觀的道長。 經(jīng)常有香客問我刊愚,道長踊跟,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,906評論 1 295
  • 正文 為了忘掉前任鸥诽,我火速辦了婚禮商玫,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘牡借。我一直安慰自己拳昌,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,928評論 6 392
  • 文/花漫 我一把揭開白布钠龙。 她就那樣靜靜地躺著炬藤,像睡著了一般御铃。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上刻像,一...
    開封第一講書人閱讀 51,718評論 1 305
  • 那天畅买,我揣著相機與錄音,去河邊找鬼细睡。 笑死谷羞,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的溜徙。 我是一名探鬼主播湃缎,決...
    沈念sama閱讀 40,442評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼蠢壹!你這毒婦竟也來了嗓违?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,345評論 0 276
  • 序言:老撾萬榮一對情侶失蹤图贸,失蹤者是張志新(化名)和其女友劉穎蹂季,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體疏日,經(jīng)...
    沈念sama閱讀 45,802評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡偿洁,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,984評論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了沟优。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片涕滋。...
    茶點故事閱讀 40,117評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖挠阁,靈堂內(nèi)的尸體忽然破棺而出宾肺,到底是詐尸還是另有隱情,我是刑警寧澤侵俗,帶...
    沈念sama閱讀 35,810評論 5 346
  • 正文 年R本政府宣布锨用,位于F島的核電站,受9級特大地震影響坡慌,放射性物質(zhì)發(fā)生泄漏黔酥。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,462評論 3 331
  • 文/蒙蒙 一洪橘、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧棵帽,春花似錦熄求、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,011評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春卿城,著一層夾襖步出監(jiān)牢的瞬間枚钓,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,139評論 1 272
  • 我被黑心中介騙來泰國打工瑟押, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留搀捷,地道東北人。 一個月前我還...
    沈念sama閱讀 48,377評論 3 373
  • 正文 我出身青樓多望,卻偏偏與公主長得像嫩舟,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子怀偷,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,060評論 2 355

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