從SDK 1.5版本以後,Android就開放它的IMF(Input Method Framework),讓我們能夠開發自己的IME。而開發IME最好的參考就是Android內建的Sample-SoftKeyboard,雖然這個例子僅包含英文和數字輸入,但是它本身還算完整和清楚,對我們開始Android開發實戰有很大協助。
什麼是IMF:
IMF(Input Method Framework),Android IMF用於支援各種IME,如軟鍵盤輸入、手寫輸入、物理鍵盤輸入(soft keyboard, hand-writing recognizers, and hard keyboard translators)。我們關注的重點是軟鍵盤輸入。
IMF結構:
一個IMF結構中包含三個主要的部分:
input method manager:管理各部分的互動。它是一個用戶端API,存在於各個應用程式的context中,用來溝通管理所有進程間互動的全域系統服務。
input method(IME):實現一個允許使用者產生文本的獨立互動模組。系統綁定一個當前的IME。使其建立和產生,決定IME何時隱藏或者顯示它的UI。同一時間只能有一個IME運行。
client application:通過IME管理器控制輸入焦點和IME的狀態。一次只能有一個用戶端使用IME。
建立一個IME:
(1)在AndroidManifest.xml
中,須把input method聲明成一個service,並且加上 intent filter (associated meta data):
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.fastinput"> <application android:label="@string/app_label"> <!-- 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> <!-- Optional activities. A good idea to have some user settings. --> <activity android:name="FastInputIMESettings" android:label="@string/fast_input_settings"> <intent-filter> <action android:name="android.intent.action.MAIN"/> </intent-filter> </activity> </application></manifest>
(2)一個InputMethodService
的生命週期如:
(3)兩類重要的視圖:
輸入視圖和候選詞視圖(the input view and the candidates view):
輸入視圖(the input view):是與使用者互動的主要發生地:按鍵,畫圖或者其他的方式。通常的實現就是簡單的用一個視圖來處理所有的工作,並且在調用 InputMethodService.onCreateInputView()的時候返回一個新的執行個體。通過調用系統的onEvaluateInputViewShow()來測試是否需要顯示輸入視圖,它是系統根據當前的上下文環境來實現的。當IME狀態改變的時候,需要調用updateInputViewShown()來重新估計一下。
候選詞視圖(the candidates view):當使用者輸入一些字元之後,IME可能需要提供給使用者一些可用的候選詞的列表。這個視圖的管理和輸入視圖不大一樣,因為這個視圖是非常的短暫的,它只是在有候選詞的時候才會被顯示。調用InputMethodService.onCreateCandidatesView()預設返回NULL. 可以用setCandidatesViewShow()來設定是否需要顯示這個視圖。正是因為這個顯示的頻繁性,所以它一般不會被銷毀,而且不會改變當前應用程式的視圖。
(4)為IME設計不同的輸入類型:
自己可以根據用途設計不同的輸入類型。如LatinIME提供以下兩種輸入介面:
(5)EditorInfo
對象
EditorInfo
對象提供不同輸入類型和文本域的各類值。
(EditorInfo.inputType & EditorInfo.TYPE_CLASS_MASK
) 可以提供不同的值,如下:
數字地區:TYPE_CLASS_NUMBER
時間:TYPE_CLASS_DATETIME
電話:TYPE_CLASS_PHONE
文本:TYPE_CLASS_TEXT
其他的還有密碼輸入等;
(6)發送文本到應用程式(
Sending text to the application)
有兩種方法將文本提交給應用程式:
1.send individual key events
2.edit the text around the cursor in the application's text field
×發送一個關鍵事件,可以利用KeyEvent對象和調用InputConnection.sendKeyEvent()
方法:
InputConnection ic = getCurrentInputConnection();long eventTime = SystemClock.uptimeMillis();ic.sendKeyEvent(new KeyEvent(eventTime, eventTime,KeyEvent.ACTION_DOWN, keyEventCode, 0, 0, 0, 0,KeyEvent.FLAG_SOFT_KEYBOARD|KeyEvent.FLAG_KEEP_TOUCH_MODE));ic.sendKeyEvent(new KeyEvent(SystemClock.uptimeMillis(), eventTime,KeyEvent.ACTION_UP, keyEventCode, 0, 0, 0, 0, KeyEvent.FLAG_SOFT_KEYBOARD|KeyEvent.FLAG_KEEP_TOUCH_MODE));
或者也可以利用這個簡便方法(推薦方法):
InputMethodService.sendDownUpKeyEvents(keyEventCode);
×在文本域編輯文本(When editing text in a text field),android.view.inputmethod.InputConnection一下有用的方法如下:
getTextBeforeCursor()
getTextAfterCursor()
deleteSurroundingText()
commitText()
例如:
InputConnection ic = getCurrentInputConnection();ic.deleteSurroundingText(4, 0);ic.commitText("Hello", 1);ic.commitText("!", 1);
(7)在提交前組合文本(Composing text before committing)
在輸入單詞或者漢字等組合詞時,可以在文本域顯示進度或者候選詞供輸入者選擇。
InputConnection ic = getCurrentInputConnection();ic.setComposingText("Composi", 1);...ic.setComposingText("Composin", 1);...ic.commitText("Composing ", 1);
8)響應物理鍵盤輸入(Intercepting hard key events)
為了響應物理鍵盤輸入,需要重寫InputMethodService.onKeyDown()
和InputMethodService.onKeyUp()
方法。調用super.onKey方法。
具體軟鍵盤執行個體可參考LatinIME source code