Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> Android開發 >> 高級開發 >> Android開發實例詳解之IMF

Android開發實例詳解之IMF

編輯:高級開發

從SDK 1.5版本以後,android就開放它的IMF(Input Method Framework),讓我們能夠開發自己的輸入法。而開發輸入法最好的參考就是Android自帶的Sample-SoftKeyboard,雖然這個例子僅包含英文和數字輸入,但是它本身還算完整和清楚,對我們開始android開發實戰有很大幫助。

一、IMF 簡介

一個IMF結構中包含三個主要的部分:

input method manager:管理各部分的交互。它是一個客戶端API,存在於各個應用程序的context中,用來溝通管理所有進程間交互的全局系統服務。

input method(IME):實現一個允許用戶生成文本的獨立交互模塊。系統綁定一個當前的輸入法。使其創建和生成,決定輸入法何時隱藏或者顯示它的UI。同一時間只能有一個IME運行。

clIEnt application:通過輸入法管理器控制輸入焦點和IME的狀態。一次只能有一個客戶端使用IME。

1 、InputManager

由UI控件(View,TextVIEw,EditText等)調用,用來操作輸入法。比如,打開,關閉,切換輸入法等。

它是整個輸入法框架(IMF)結構的核心API,處理應用程序和當前輸入法的交互。可以通過Context.getSystemService()來獲取一個InputMethodManager的實例。

在開發過程中,最基礎最重要的就是養成閱讀API的習慣。優秀的程序員要養成把自己關在小黑屋裡,斷絕與外界的聯網和聯系,僅僅靠自己電腦中的開發環境和API文檔,以及漂亮女僕送來的每天三頓飯,寫出優秀的程序。這個在武俠小說中叫閉關,在軟件開發中叫Clean Room,哈哈。

android的API文檔在:%SDK_ROOM%/docs/reference/index.Html,

InputManager類的位置:%SDK_ROOM%/docs/reference/android/vIEw/inputmethod/InputMethodManager.Html

由於,該類跟本次要講的Sample關系不大,這裡就不詳細分析,請各位自行閱讀API doc吧。

2 、InputMethodService

包括輸入法內部邏輯,鍵盤布局,選詞等,最終把選出的字符通過commitText提交出來。實現輸入法的基礎就是名為InputMethodService的類,比如你要實現一個谷歌輸入法,就是要extends本類。我們接下來要學習的SoftKeyboard Sample也是extends本類。InputMethodService類的位置在:%SDK_ROOM%/docs/reference/android/inputmethodservice/InputMethodService.Html

InputMethodService是InputMethod的一個完整實現,你可以再在其基礎上擴展和定制。它的主要方法如下:

◆onInitializeInterface() 顧名思義,它在初始化界面的時候被調用,而一般是由於配置文件的更改導致該函數的執行

◆onBinndInput() 它在另外的客戶端和該輸入法連接時調用

◆onStartInput() 非常重要的一個回調,它在編輯框中用戶已經開始輸入的時候調用。比如,當點擊一個輸入框,我們需要根據這個輸入框的信息,設置輸入法的一些特性,這個在Sample中很有體會。

◆onCreateInputVIEw() 返回一個層次性的輸入視圖,而且只是在這個視圖第一次顯示的時候被調用

◆onCreateCandidatesView() 同onCreateInputVIEw(),只不過創建的是候選框的視圖。

◆onCreateExtractTextVIEw() 比較特殊,是在全屏模式下的一個視圖。

◆onStartInputVIEw() 在輸入視圖被顯示並且在一個新的輸入框中輸入已經開始的時候調用。

基本上輸入法的定制,都是圍繞在這個類來實現的,它主要提供的是一個基本的用戶界面框架(包括輸入視圖,候選詞視圖和全屏模式),但是這些都是要實現者自己去定制的。這裡的實現是讓所有的元素都放置在了一個單一的由InputMethodService來管理的窗口中。它提供了很多的回調API,需要我們自己去實現。一些默認的設置包括:

◆軟鍵盤輸入視圖,它通常都是被放置在屏幕的下方。

◆候選詞視圖,它通常是放置在輸入視圖的上面。

◆當我們輸入的時候,需要改變應用程序的界面來適應這些視圖的放置規則。比如在android上面輸入,編輯框會自動變形騰出一個軟鍵盤的位置來。

兩個非常重要的視圖:

1. 軟輸入視圖。是與用戶交互的主要發生地:按鍵,畫圖或者其他的方式。通常的實現就是簡單的用一個視圖來處理所有的工作,並且在調用 onCreateInputView()的時候返回一個新的實例。通過調用系統的onEvaluateInputViewShow()來測試是否需要顯示輸入視圖,它是系統根據當前的上下文環境來實現的。當輸入法狀態改變的時候,需要調用updateInputVIEwShown()來重新估計一下。

2. 候選詞視圖。當用戶輸入一些字符之後,輸入法可能需要提供給用戶一些可用的候選詞的列表。這個視圖的管理和輸入視圖不大一樣,因為這個視圖是非常的短暫的,它只是在有候選詞的時候才會被顯示。可以用setCandidatesVIEwShow()來設置是否需要顯示這個視圖。正是因為這個顯示的頻繁性,所以它一般不會被銷毀,而且不會改變當前應用程序的視圖。

最後,關於文本的產生,這是一個IME的最終目的。它通過InputConnection來鏈接IME和應用程序的:能夠直接產生想要的按鍵信息,甚至直接在候選和提交的文本中編輯。當用戶在不同的輸入目標之間切換的時候,IME會不斷的調用onFinishInput() 和 onStartInput()。在這兩個函數中,需要反復做的就是復位狀態,並且應對新的輸入框的信息。

以上是一個輸入法的最基本的介紹,下面將根據Sample中的SoftKeyboard來說明這些問題

二、創建Eclipse工程

這裡使用最新版本的android SDK 2.3.3下的SoftKeyboard Sample來創建工程,其實,從1.5版本,該Sample就已經存在了。同時,由於SoftKeyboard會使人誤解為KeyBoard的子類,這裡特別改名為InputMethodServiceSample,更符合其功能和特性。

輸入法在Android中的本質就是一個Service,假設用戶剛剛啟動Android,用戶移動焦點首次進入文本編輯框時,android便會通知Service開始進行初始化工作。於是便有了如圖中的一系列動作。

追根溯源,onCreate方法繼承至Service類,其意義和其他Service的是一樣的。Sample在這裡,做了一些非UI方面的初始化,即字符串變量詞匯分隔符的初始化。

接下來執行onInitializeInterface,這裡是進行UI初始化的地方,創建以後和配置修改以後,都會調用這個方法。Sample在這裡對Keyboard進行了初始化,從XML文件中讀取軟鍵盤信息,封裝進Keyboard對象。

第三個執行的就是onStartInput方法,在這裡,我們被綁定到了客戶端,接收所有關於編輯對象的詳細信息。

第四個執行的方法是onCreateInputView,在用戶輸入的區域要顯示時,這個方法由框架調用,輸入法首次顯示時,或者配置信息改變時,該方法就會被執行。在該方法中,對inputvIEw進行初始化:讀取布局文件信息,設置onKeyboardActionListener,並初始設置 keyboard。

第五個方法是onCreateCandidatesView,在要顯示候選詞匯的視圖時,由框架調用。和onCreateInputView類似。在這個方式中,對candidatevIEw 進行初始化。

第六個方法,也是最後一個方法,即onStartInputView,正是在這個方法中,將inputvIEw和當前keyboard重新關聯起來。

在上面的六個方法中,onCreateInputView和onCreateCandidatesVIEw兩個方法只有在初始化時才會執行一次,除非有配置信息發生改變。那麼究竟什麼是配置信息發生改變呢?在看InputMethodService的API文檔時,可以看到有一個方法onConfigurationChanged,根據文檔解釋,這個方法主要負責配置更改的情況。在示例中,其沒有override這個方法,但是在android源碼包中的PinyinIME中,有使用這個方法,有興趣的朋友可以在看完SoftKeyboard Sample之後,看看PinyinIME的源碼。

關於本類中其它的一些方法,由於比較直觀,就不進行講解了,感興趣的朋友可以參考《android sdk中 softkeyboard的自己解析(4) 》。

五、輸入法調試

通過使用調試模式加斷點的方式,有助於我們更好的理解輸入法的時序和每個類及其方法的功能和調用持續。

這裡使用Eclipse的DDMS透視圖進行調試,具體介紹參考《用Eclipse開發和調試android應用程序 》

首先切換到DDMS模式,在這個模式下面,DDMS將鏈接到正在運行的手機或模擬器,並且能夠提取手機上面的各種信息,比如線程,還有各個正在後台運行的服務等等。點擊工具條上的“Debug selected Process”,就能夠將調試器植入到這個服務上面。

DDMS模式

之後切換到debug模式,就會發現調試器已經鏈接到了這個模擬器,然後就可以像調試普通的程序一樣調試這個輸入法了。

debug模式

通過debug模式,我們可以發現,輸入法首先執行的onCreateInputView-> onCreateCandidatesVIEw,而在這個時候,這個輸入法的界面一點兒都還沒有顯現出來。當我們在一個輸入框中點擊鼠標時,系統會產生一個事件,最開始就被輸入法捕獲,然後再將控制權交給這個輸入法。另外,切換對象的時候,輸入法總是認為是一次輸入的結束,然後進行一系列的reset工作。所有的鍵盤等事件,都會首先傳遞給輸入法,所以,如果一個按鍵事件不是我們所能夠處理的問題,我們需要將這個事件繼續傳遞下去,而不要丟棄了,因為這可能是別的控件的事情。

在發送消息的界面,在輸入完TO某人之後,點擊content輸入框,首先調用的是onFinishInput,也就是結束上一次的輸入,准備這次的輸入。之後調用的是onStartInputVIEw,讓界面顯示出來。接著調用onStartInput,表示開始正式的輸入。在這過程中,要完成根據不同的輸入框,選擇不同的鍵盤,當你輸入一個鍵,首先觸發的是onKey回調,在這裡要判斷是輸入的普通字符,還是控制性的字符,比如刪除,返回等等。比如這裡輸入一個 'g',然後會調用處理普通字符的函數handleCharacter。這裡的策略就是,輸入一個普通字符,就將Composing增加,並且更新這個候選詞的列表。這裡有一個很微妙的開關,就是mPrediction,它就是判斷是否是需要保存這個Composing。在比如說URL框中輸入的時候,就會置這個開關為關,直接將鍵入的輸入到文本框中去。

為了測試所有的函數,你必須想出一種輸入方式,讓每個函數你都能執行到,那你就能夠看清楚輸入法的本來面目。

請各位朋友自己試試,對閱讀和理解源代碼的流程、時序和生命周期很有好處。也可以方便的找到自己的代碼的bug。

六、輸入法的調用

希望從一個VIEw上調用輸入法和接收輸入法傳過來的字符串,可以通過調用EditText這個widget。但是,如果要做出很炫很個性的輸入法,就必須自己去和EditText一樣連接輸入法,介紹如下:

首先,定義一個繼承自BaseInputConnection的類。前文提到過,輸入法是通過commitText來提交選中字符。

  1. public class MyBaseInputConnection extends BaseInputConnection{
  2. public MyBaseInputConnection(View targetVIEw, boolean fullEditor) {
  3. super(targetVIEw, fullEditor);
  4. }
  5. public static String tx="";
  6. //輸入法程序就是通過調用這個方法把最終結果輸出來的
  7. @Override
  8. public boolean commitText(CharSequence text, int newCursorPosition) {
  9. tx = text.toString();
  10. return true;
  11. }
  12. }

BaseInputConnection相當於一個InputMethodService和VIEw之間的一個通道。每當InputMethodService產生一個結果時,都會調用BaseInputConnection的commitText方法,把結果傳遞出來。

之後,采用如下方式,呼出輸入法,並且把自定義的BaseInputConnection通道傳遞給InputMethodService。

  1. public class MyVIEw extends XXVIEw ...{
  2. //得到InputMethodManager
  3. InputMethodManager input = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
  4. //定義事件處理器
  5. ResultReceiver receiver = new ResultReceiver(new Handler() {
  6. public void handleMessage(Message msg) {
  7. }
  8. });
  9. ...
  10. //在你想呼出輸入法的時候,調用這一句
  11. input.showSoftInput(this, 0, mRR);
  12. ...
  13. @Override
  14. //這個方法繼承自VIEw。把自定義的BaseInputConnection通道傳遞給InputMethodService
  15. public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
  16. return new MyBaseInputConnection(this, false);
  17. }
  18. }

低級界面上面,自己調用輸入法並接收輸入法的輸出結果,就是這樣的。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved