文字和輸入:建立一個IME:簡介
輸入法編輯器(IME)是使用者可以控制,以讓使用者輸入文字的編輯器。 Android提供了一個可擴充套件的輸入法框架,允許應用程式為使用者提供替代輸入法,如螢幕鍵盤,甚至語音輸入。 安裝所需的IME後,使用者可以從系統設定中選擇要使用的IME,並在整個系統中使用它; 一次只能啟用一個IME。
要向Android系統新增IME,您可以建立一個包含擴充套件InputMethodService類的Android應用程式。 此外,您通常會建立一個將設定傳遞給IME服務的“設定”活動。 您還可以定義顯示為系統設定一部分的設定UI。
本指南涵蓋以下內容:
1、IME生命週期。
2、在應用程式清單中宣告TIME元件。
3、IME API。
4、設計IME UI。
5、從IME傳送文字到應用程式。
6、使用IME子型別。
如果您以前沒有使用IME,您應該首先閱讀介紹性的螢幕輸入法。 此外,SDK中包含的SoftKeyboard示例應用程式包含可以修改的示例程式碼,以便你可以開始構建自己的IME。
一、IME生命週期
下圖描述了IME的生命週期:
圖1. IME的生命週期。
以下部分介紹如何實現與此生命週期之後的IME相關聯的UI和程式碼。
二、在清單中宣告IME元件
在Android系統中,IME是一個包含特殊IME服務的Android應用程式。 應用程式的清單檔案必須宣告服務,請求必需的許可權,提供與action.view.InputMethod操作匹配的意圖過濾器,並提供定義IME特徵的元資料。 另外,為了提供允許使用者修改IME的行為的設定介面,您可以定義可以從“系統設定”啟動的“設定”活動。
以下程式碼段聲明瞭IME服務。 它要求BIND_INPUT_METHOD允許服務將IME連線到系統,設定一個與操作android.view.InputMethod匹配的意圖過濾器,並定義IME的元資料:
<!-- 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的設定活動。 它具有ACTION_MAIN的意圖過濾器,表示此活動是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設定的訪問。
三、輸入法API
特定於IME的類可以在android.inputmethodservice和android.view.inputmethod包中找到。 KeyEvent類對於處理鍵盤字元很重要。
IME的中心部分是一個服務元件,一個擴充套件InputMethodService的類。 除了實現正常的服務生命週期之外,該類還提供了回撥,以提供您的IME的UI,處理使用者輸入,並將文字傳遞到當前具有焦點的欄位。 預設情況下,InputMethodService類提供了用於管理IME的狀態和可見性以及與當前輸入欄位通訊的大多數實現。
以下類也很重要:
將從InputMethod返回到正在接收其輸入的應用程式的通訊通道定義。 您可以使用它來讀取游標周圍的文字,將文字提交到文字框,並將原始金鑰事件傳送到應用程式。 應用程式應該擴充套件這個類,而不是實現基本介面InputConnection。
檢視的擴充套件,用於呈現鍵盤並響應使用者輸入事件。 鍵盤佈局由鍵盤例項指定,您可以在XML檔案中定義。
四、設計輸入法UI
IME有兩個主要的視覺元素:輸入檢視和候選檢視。 您只需要實現與您正在設計的輸入法相關的元素。
一)、輸入檢視
輸入檢視是UI,使用者以鍵盤,手寫或手勢的形式輸入文字。 當IME第一次顯示時,系統呼叫onCreateInputView()回撥。 在實現此方法時,您將建立要在IME視窗中顯示的佈局,並將佈局返回到系統。 此程式碼段是實現onCreateInputView()方法的示例:
@Override
public View onCreateInputView() {
MyKeyboardView inputView =
(MyKeyboardView) getLayoutInflater().inflate(R.layout.input, null);
inputView.setOnKeyboardActionListener(this);
inputView.setKeyboard(mLatinKeyboard);
return mInputView;
}
在此示例中,MyKeyboardView是一個呈現鍵盤的KeyboardView的自定義實現的例項。 如果您正在構建傳統的QWERTY鍵盤,請參閱KeyboardView類。
二)、候選檢視
候選檢視是UI,其中IME顯示潛在的單詞更正或使用者要選擇的建議。 在IME生命週期中,當準備好顯示候選檢視時,系統呼叫onCreateCandidatesView()。 在實現此方法時,返回顯示單詞建議的佈局,如果不想顯示任何內容,則返回null。 空響應是預設行為,因此如果不提供建議,則不需要實現。
有關提供使用者建議的示例實現,請參閱SoftKeyboard示例應用程式。
三)、UI設計考慮
本節介紹IME的一些特定UI設計注意事項。
1、處理多個螢幕尺寸
您的IME的UI必須能夠擴充套件不同的螢幕尺寸,並且還必須處理橫向和縱向方向。 在非全屏IME模式下,為應用程式留出足夠的空間來顯示文字欄位和任何相關的上下文,以便IME不超過螢幕的一半佔用。 在全屏IME模式下,這不是一個問題。
2、處理不同的輸入型別
Android文字欄位允許您設定特定的輸入型別,例如自由格式的文字,數字,URL,電子郵件地址和搜尋字串。 當您實現新的IME時,您需要檢測每個欄位的輸入型別併為其提供適當的介面。 但是,您不必設定IME來檢查使用者輸入的輸入型別的有效文字; 這是擁有文字欄位的應用程式的責任。
例如,以下是Android平臺提供的拉丁語IME提供的文字和電話號碼輸入的介面截圖:
圖2.拉丁語IME輸入型別。
當輸入欄位接收到焦點並且您的IME啟動時,系統呼叫onStartInputView(),傳遞一個EditorInfo物件,該物件包含有關文字欄位的輸入型別和其他屬性的詳細資訊。 在此物件中,inputType欄位包含文字欄位的輸入型別。
輸入型別欄位是包含各種輸入型別設定的位模式的int。 要測試文字欄位的輸入型別,請使用常量TYPE_MASK_CLASS進行掩碼,如下所示:
inputType & InputType.TYPE_MASK_CLASS
輸入型別位模式可以有幾個值之一,包括:
用於輸入數字的文字欄位。 如上一螢幕截圖所示,拉丁語IME顯示此型別欄位的數字鍵盤。
用於輸入日期和時間的文字欄位。
用於輸入電話號碼的文字欄位。
用於輸入所有支援的字元的文字欄位。
這些常量在InputType的參考文件中有更詳細的描述。
inputType欄位可以包含指示文字欄位型別變體的其他位,例如:
用於輸入密碼的TYPE_CLASS_TEXT的變體。 輸入法將顯示dingbats而不是實際的文字。
用於輸入Web URL和其他統一資源識別符號(URI)的TYPE_CLASS_TEXT的變體。
用於從字典,搜尋或其他工具輸入應用程式“自動完成”的文字的TYPE_CLASS_TEXT的變體。
當您測試這些變體時,請記住使用適當的常量遮蔽輸入型別。 可用的掩碼常量在輸入型別的參考文件中列出。
注意:在您自己的IME中,確保在將其傳送到密碼欄位時正確處理文字。 在輸入檢視和候選檢視中隱藏使用者介面中的密碼。 還要記住,您不應該在裝置上儲存密碼。 要了解更多資訊,請參閱“安全設計指南”。
五、傳送文字到應用程式
當用戶使用IME輸入文字時,您可以通過傳送單個鍵事件或通過在應用程式的文字欄位中編輯游標周圍的文字來嚮應用程式傳送文字。 在這兩種情況下,您都可以使用InputConnection例項來傳遞文字。 要獲取此例項,請呼叫InputMethodService.getCurrentInputConnection()。
一)、編輯游標周圍的文字
當您處理文字欄位中現有文字的編輯時,BaseInputConnection中的一些更有用的方法是:
返回包含當前游標位置之前所請求字元數的CharSequence。
返回一個包含當前游標位置後所請求字元數的CharSequence。
刪除當前游標位置之前和之後的指定字元數。
將一個CharSequence提交到文字欄位並設定一個新的游標位置。
例如,以下程式碼段顯示瞭如何使用文字“Hello!”替換游標左側的四個字元:
InputConnection ic = getCurrentInputConnection();
ic.deleteSurroundingText(4, 0);
ic.commitText("Hello", 1);
ic.commitText("!", 1);
二)、提交前撰寫文字
如果您的IME進行文字預測或需要多個步驟來組合字形或單詞,則可以在文字欄位中顯示進度,直到使用者提交單詞,然後可以將部分組合替換為已完成的文字。 當您將其傳遞給setComposingText()時,可以通過新增“span”來對文字進行特殊處理。
以下程式碼段顯示瞭如何在文字欄位中顯示進度:
InputConnection ic = getCurrentInputConnection();
ic.setComposingText("Composi", 1);
ic.setComposingText("Composin", 1);
ic.commitText("Composing ", 1);
以下螢幕截圖顯示了使用者如何顯示:
圖3.提交前撰寫文字。
三)、攔截硬體關鍵事件
即使輸入法視窗沒有明確的焦點,它首先接收硬體金鑰事件,也可以選擇使用它們或將其轉發到應用程式。 例如,您可能需要使用方向鍵在UI中導航,以便在組合期間進行候選人選擇。 您可能還需要捕獲後退鍵以關閉源自輸入法視窗的任何彈出視窗。
要擷取硬體金鑰,請覆蓋onKeyDown()和onKeyUp()。 請參閱軟鍵盤示例應用程式作為示例。
記住對於你不想處理自己的鍵,要呼叫super()方法。
六、建立IME子型別
子型別允許IME公開IME支援的多種輸入模式和語言。 子型別可以表示:
1、一個區域設定,如en_US或fr_FR。
2、輸入模式,如語音,鍵盤或手寫。
3、特定於IME的其他輸入樣式,表單或屬性,如10鍵或Qwerty鍵盤佈局。
基本上,模式可以是諸如“鍵盤”,“聲音”等的任何文字。 子型別也可以暴露這些的組合。
子型別資訊用於通知欄中可用的IME切換器對話方塊,也用於IME設定。 該資訊還允許框架直接提出IME的特定子型別。 構建IME時,使用子型別工具,因為它可以幫助使用者識別和切換不同的IME語言和模式。
您可以使用<subtype>元素在輸入法的XML資原始檔之一中定義子型別。 以下程式碼片段定義了一個具有兩個子型別的IME:美國英語區域設定的鍵盤子型別,法國法語區域的另一個鍵盤子型別:
<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" ... />
</input-method>
要確保您的子型別在UI中正確標記,請使用%s獲取與子型別的區域標籤相同的子型別標籤。 這在下面的兩個片段中演示。 第一個程式碼片段顯示了輸入法XML檔案的一部分:
<subtype
android:label="@string/label_subtype_generic"
android:imeSubtypeLocale="en_US"
android:icon="@drawable/icon_en_us"
android:imeSubtypeMode="keyboard" />
下一個片段是IME的strings.xml檔案的一部分。 由輸入法UI定義用於設定子型別的標籤的字串資源label_subtype_generic定義為:
<string name="label_subtype_generic">%s</string>
此設定使子型別的顯示名稱與區域設定相匹配。 例如,在任何英文區域中,顯示名稱為“英語(美國)”。
一)、從通知欄中選擇TIME子型別
Android系統管理所有IME公開的所有子型別。 IME子型別被視為他們所屬的IME模式。 在通知欄中,使用者可以為當前設定的IME選擇可用的子型別,如以下螢幕截圖所示:
圖4.從通知欄中選擇IME子型別。
圖5.在系統設定中設定子型別首選項。
二)、從系統設定中選擇IME子型別
使用者可以在“系統設定”區域的“語言和輸入”設定面板中控制子型別的使用方式。 在SoftKeyboard示例應用程式中,InputMethodSettingsFragment.java檔案包含一個在IME設定中促進子型別啟用程式的實現。 有關如何在IME中支援輸入法子型別的更多資訊,請參閱Android SDK中的SoftKeyboard示例應用程式。
圖6.選擇IME的語言。
七、在IME子型別之間切換
您可以通過提供切換鍵(例如地球形語言圖示)作為鍵盤的一部分,允許使用者在多個IME子型別之間輕鬆切換。 這樣做大大提高了鍵盤的可用性,並可以幫助避免使用者的沮喪。 要啟用此類切換,請執行以下步驟:
1、宣告支援在輸入法的XML資原始檔中切換ToNextInputMethod =“true”。 您的宣告應與以下程式碼片段相似:
<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、呼叫shouldOfferSwitchingToNextInputMethod()方法。
3、如果方法返回true,則顯示切換鍵。
4、當用戶點選切換鍵時,呼叫switchToNextInputMethod(),將false傳遞給第二個引數。 值false表示系統平等對待所有子型別,不管它們屬於什麼IME。 指定true需要系統在當前IME中迴圈遍歷子型別。
注意:在Android 5.0(API級別21)之前,switchToNextInputMethod()不知道supportsSwitchingToNextInputMethod屬性。 如果使用者切換到沒有切換鍵的IME,他或她可能會卡在該IME中,無法輕鬆切換出來。
八、一般IME注意事項
在實施TIME時,還有其他一些需要考慮的事項:
1、為使用者提供一種直接從IME的使用者介面設定選項的方法。
2、由於可能會在裝置上安裝多個TIME,為使用者提供一種直接從輸入法UI切換到不同IMEI的方式。
3、快速啟動IME的UI。 預先載入或載入任何大量資源,以便使用者在點選文字欄位後立即看到IME。 快取資源和檢視,以便隨後呼叫輸入法。
4、相反,您應該在隱藏輸入法視窗後立即釋放大量記憶體分配,以便應用程式可以有足夠的記憶體來執行。 如果IME處於隱藏狀態幾秒鐘,請考慮使用延遲訊息來釋放資源。
5、確保使用者可以為與IME相關聯的語言或語言環境輸入儘可能多的字元。 請記住,使用者可能會使用密碼或使用者名稱中的標點符號,因此您的IME必須提供許多不同的字元,以便使用者輸入密碼並訪問裝置。