精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

Android開發(fā)實例詳解之IMF

移動開發(fā) Android
本博前面的文章介紹了Android開發(fā)環(huán)境的搭建和模擬器的常用操作。本次,將以Android Sample中經典的SoftKeyboard項目為例,詳細解析Android上一個小型項目的開發(fā)過程和注意事項。

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

一、IMF 簡介

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

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

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

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

1 、InputManager

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

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

在開發(fā)過程中,最基礎最重要的就是養(yǎng)成閱讀API的習慣。優(yōu)秀的程序員要養(yǎng)成把自己關在小黑屋里,斷絕與外界的聯網和聯系,僅僅靠自己電腦中的開發(fā)環(huán)境和API文檔,以及漂亮女仆送來的每天三頓飯,寫出優(yōu)秀的程序。這個在武俠小說中叫閉關,在軟件開發(fā)中叫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() 顧名思義,它在初始化界面的時候被調用,而一般是由于配置文件的更改導致該函數的執(zhí)行

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

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

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

◆onCreateCandidatesView() 同onCreateInputView(),只不過創(chuàng)建的是候選框的視圖。

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

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

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

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

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

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

兩個非常重要的視圖:

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

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

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

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

二、創(chuàng)建Eclipse工程

這里使用***版本的Android SDK 2.3.3下的SoftKeyboard Sample來創(chuàng)建工程,其實,從1.5版本,該Sample就已經存在了。同時,由于SoftKeyboard會使人誤解為KeyBoard的子類,這里特別改名為InputMethodServiceSample,更符合其功能和特性。

 創(chuàng)建Eclipse工程

點擊Finish,完成項目的創(chuàng)建,可以看到項目工程結構如下:

  創(chuàng)建Eclipse工程

在Android SDK 2.3.3模擬器上運行本Sample,需要在Setting中選擇使用本Sample,需要在Language&keyboard中選中本Sample的名稱。

 創(chuàng)建Eclipse工程

創(chuàng)建Eclipse工程

當嘗試選中Sample Soft Keyboard時,Android會出現安全提示。IME的確要選擇自己信任的,因為它可以收集和記錄所有你的輸入,這個特性如果被有心人利用會很恐怖。

選中Sample Soft Keyboard作為我們的輸入法之后,進入需要輸入法的地方,這里以短信界面作為范例,在輸入框中長按,會出現“編輯文本”選單,點擊“輸入法”即可進入當前輸入界面的輸入法選擇框。就可以使用輸入法切換到本輸入法看到它的keyboard。

 創(chuàng)建Eclipse工程

創(chuàng)建Eclipse工程

之后就可以看到Soft keyboard鍵盤如下:

創(chuàng)建Eclipse工程

三、配置和資源文件解析

除去源代碼將在后文統(tǒng)一分析之外,這里介紹下配置和資源文件。

1. AndroidMainifest.xml

每個Android應用都會有的配置描述文件。在這里,Sample把自己聲明成了服務,而且綁定在了輸入法之上。它的intent-filter是直接用的InputMethod接口,這也是所有的輸入法的接口。

2. res 目錄

放置resource,即資源文件,里面蠻多東西的,具體如下。

(1) drawable目錄,放置的是圖標文件。

(2) values目錄,包含strings.xml以及一些自定義的類型和值的xml文件。

strings.xml

― ime_name 定義了該輸入法的名字

― word_separators 詞的分隔符,即輸入過程中可能用來表示一個詞輸入完成的符號,比如空格,標點等等)

― label_xx_key 為軟鍵盤定義確認鍵的標簽。在后面代碼解析中可以看到,程序會根據輸入框的信息來設置EnterKey的圖標或者標簽。如:在一個網址上面輸入,就會顯示一個搜索的圖標,而在編輯短信時,如果在收信人寫,那么EnterKey就是Next標簽,用來直接跳到短信正文部分。

dimens.xml,定義軟鍵盤的尺寸信息,包括鍵高(key_height),候選詞字體的高度(candidate_font_height),候選詞垂直間隙(candidate_vertical_padding)。

color.xml,定義候選詞的背景顏色,比如正常(candidate_normal),推薦(candidate_recommended),背景(candidate_background)和其它(candidate_other)等顏色。

(3) layout目錄,保存布局配置文件。這里只有一個配置文件:input.xml,它定義的是輸入視圖的信息,包括id(android:id="@+id/keyboard"),放置在屏幕下方(android:layout_alignParentBottom="true"),水平***填充(android:layout_width="match_parent"),垂直包含子內容(android:layout_height="wrap_content")。

(4) xml目錄,文件如下:

method.xml,為搜索管理提供配置信息。

qwerty.xml,英文字符的全鍵盤布局文件。定義很直觀,很容易就可以看懂。

symbols_shift.xml和symbols.xml,是標點字符的全鍵盤布局文件。

四、源代碼解析

(一)概述

從InputMethodServiceSample項目可以看出實現一個輸入法至少需要CandidateView, LatinKeyboard, LatinKeyboardView,SoftKeyboard這四個文件:

◆CandidateView負責顯示軟鍵盤上面的那個候選區(qū)域。

◆LatinKeyboard負責解析并保存鍵盤布局,并提供選詞算法,供程序運行當中使用。其中鍵盤布局是以XML文件存放在資源當中的。比如我們在漢字輸入法下,按下b、a兩個字母。LatinKeyboard就負責把這兩個字母變成爸、把、巴等顯示在CandidateView上。

◆LatinKeyboardView負責顯示,就是我們看到的按鍵。它與CandidateView合起來,組成了InputView,就是我們看到的軟鍵盤。

◆SoftKeyboard繼承了InputMethodService,啟動一個輸入法,其實就是啟動一個InputMethodService,當SoftKeyboard輸入法被使用時,啟動就會啟動SoftKeyboard這個Service。

(二)LatinKeyboard.java

軟鍵盤類,直接繼承了Keyboard類,并定義一個xml格式的Keyboard的布局,來實現一個輸入拉丁文的鍵盤。這里只是創(chuàng)建一個鍵盤對象,并不對具體的布局給出手段。

為了更好的理解LatinKeyboard類,這里簡單介紹一下Keyboard類。Keyboard可以載入一個用來顯示鍵盤布局的xml來初始化自己,并且可以保存這些鍵盤的鍵的屬性。他有三個構造函數:

◆Keyboard(Context context, int xmlLayoutResId),用語境和xml資源id索引xml文件來創(chuàng)建。

◆Keyboard(Context context, int xmlLayoutResId, int modeId),這個和上面差不多,只不過多了一個modeld。

◆Keyboard(Context context, int layoutTemplateResId, CharSequence characters, int columns, int horizontalPadding),這個比較復雜,用一個空xml布局模板創(chuàng)建一個鍵盤,然后用指定的characters按照從左往右,從上往下的方式填滿這個模板。

本文件源碼前面完全繼承keyboard,直接用了父類構造函數進行初始化。

這里因為重寫了Keyboard類的createKeyFromXml(Resources res, Row parent, int x, int y, XmlResourceParser parser),為了要返回一個Key對象,干脆直接創(chuàng)建LatinKey對象好了。從這里我們能看出面向對象和使用框架的要求。

接著,本文件重載了一個createKeyFromXml的函數,這是一個回調函數,它在鍵盤描繪鍵的時候調用,從一個xml資源文件中載入一個鍵,并且放置在(x,y)坐標處。它還判斷了該鍵是否是回車鍵,并保存起來。在這里,為了要返回一個Key對象,于是直接創(chuàng)建內部類的LatinKey對象。從這里我們能看出面向對象和使用框架的要求。

此外,還有一個函數是:setImeOptions,它是根據編輯框的當前信息,來為這個鍵盤的回車鍵設置適當的標簽。輸入框的不同,會產生不同的回車鍵的label或者icon。在這個函數中,有一個技巧是用了一些imeOption的位信息,比如IME_MASK_ACTION等等。主要是查看的EditorInfo的Action信息,這里有:

◆IME_ACTION_GO: go操作,將用戶帶入到一個該輸入框的目標的動作。確認鍵將不會有icon,只有l(wèi)abel: GO

◆IME_ACTION_NEXT: next操作,將用戶帶入到該文本框的寫一個輸入框中。如: 編輯短消息的時候,內容就是收件人手機號碼框的next文字域。它也只是一個NEXT label就行了。

◆IME_ACTION_SEARCH: search操作,默認動作就是搜索。如: 在URL框中輸入的時候,默認的就是search操作,它提供了一個像放大鏡一樣的icon。

◆IME-ACTION_SEND: send操作,默認動作就是發(fā)送當前的內容。如: 短消息的內容框里面輸入的時候,后面通常就是一個發(fā)送操作。它也是只提供一個Label:SEND

◆DEFAULT: 默認情況下表示文本框并沒有什么特殊的要求,所以只需要設置return的icon即可。

***,它還定義了一個內部類——LatinKey,它直接繼承了Key,來定義一個單獨的鍵,它唯一重載的函數是isInside(int x , int y ),用來判斷一個坐標是否在該鍵內。它重載為判斷該鍵是否是CANCEL鍵,如果是則把Y坐標減少10px,按照他的解釋是用來還原這個可以關掉鍵盤的鍵的目標區(qū)域。

(三)LatinKeyboardView.java

這里就是個View,自然也繼承自View,因為前面創(chuàng)建的鍵盤只是一個概念,并不能實例出來一個UI,所以需要借助于一個VIEW類來進行繪制。這個類簡單的繼承了KeyboardView類,然后重載了一個動作方法,就是onLongPress。

它在有長時間按鍵事件的時候會調用,首先判斷這個按鍵是否是CANCEL鍵,如果是的話就通過調用 KeyboardView被安置好的OnKeyboardActionListener對象,給鍵盤發(fā)送一個OPTIONS鍵被按下的事件。它是用來屏蔽CANCEL鍵,然后發(fā)送了一個未知的代碼的鍵。

(四)CandidateView.java

CandidateView是一個候選字顯示view,它提供一個候選字選擇的視圖,直接繼承于View類即可。在我們輸入字符時,它應該能根據字符顯示一定的提示,比如拼音同音字啊,聯想的字啊之類的。

1. 先看它定義了那些重要變量:

◆mService: candidateView的宿主類,即該view是為什么輸入法服務的。

◆mSuggestions: 建議。比如說當我們輸入一些字母之后輸入法希望根據輸入來進行聯想建議。

◆mSelectedIndex: 用戶選擇的詞的索引。

◆mSelectionHighlight: 描繪選擇區(qū)域高亮的類。

◆mTypedWordValid: 鍵入的word是否合法正確。

◆mBgPadding: 背景填充區(qū)域。

◆mWordWidth: 每個候選詞的寬度。

◆mWordX:每個候選詞的X坐標。有了這兩個變量,就能夠在屏幕上準確的繪制出該候選鍵。

◆mColor*:定義了各種顏色。

◆mPaint: 一個繪圖類,后面會用到

◆mVerticalPadding: 垂直填充區(qū)域。

◆mTargetScrollX: 目標滾動的橫坐標,即要將目標滾動到何處。

◆mTotalWidth: 總的寬度

◆mGestureDetector: 聲明一個手勢監(jiān)測器

GestureDetector對象似乎很少見,讓我們了解一下android.view.GestureDetector。這是一個與動作事件相關的類,可以用來檢測各種動作事件,這里稱之為:手勢監(jiān)測器。它的回調函數是GestureDetector.OnGestureListener,在動作發(fā)生時執(zhí)行,而且只能在觸摸時發(fā)出,用滾動球無效。要使用這個通常要先建立一個對象,如同代碼里體現的,然后設置GestureDetector.OnGestureListener 同時在 onTouchEvent(MotionEvent)中寫入動作發(fā)生要執(zhí)行的代碼。

2. 構造函數,主要是對一些變量的初始化工作。

首先初始化了mSelectionHighlight,這是一個drawable對象,并利用drawable的setState方法設置這個drawable的初始狀態(tài)。同時在res目錄下加入一個color.xml文件來定義用到的所有顏色資源,然后用R索引,這些資源可以被加入到自己的R.java的內容里,可以直接引用。 剩下的內容就是初始化背景,選中,未選中時的view的背景顏色,這里都是在前面color.xml內定義的了。用這樣的方式獲得:

Resources r = context.getResources();

獲得當前資源對象的方法。

setBackgroundColor(r.getColor(R.color.candidate_background));

然后初始化了一個手勢檢測器(gesturedetector),它的Listener重載了一個方法,就是onScroll,這個類是手勢檢測器發(fā)現有scroll動作的時候觸發(fā)。在這個函數里,主要是進行滑動的判斷。

這里用到了很多view下的方法:getScrollX();getWidth();scrollTo(sx, getScrollY());invalidate();我們分別解釋如下:

◆getScrollX():獲得滾動后view的橫坐標

◆scrollTo():滾動到目標坐標

◆getScrollY():獲得滾動后view的縱坐標

◆invalidate():使view重畫

在這里,distanceX是上次調用onscroll后滾動的X軸距離。假設這個view之前沒有被滾動過,***次滾動且坐標在顯示區(qū)域內,sx=getScrollX()+distanceX,則view就scrollTo這個位置。如果sx超過了***顯示寬度,則scrollTo就滾想原先sx處,也就是不動。也就是說:系統(tǒng)滾動產生一個慣性的感覺,當你把view實際到了X坐標點,系統(tǒng)再給你加一個distanceX,這個distanceX不是兩個動作之間的距離,應該是上一個滾動動作的停止點和本次滾動動作的停止點之間的距離,這個距離系統(tǒng)自己算,我們不用管,只要到了***邊界,view就不再滾動,或者說是原地滾動。

接下來:

◆setHorizontalFadingEdgeEnabled(true);// 設置view在水平滾動時,水平邊是否淡出。

◆setWillNotDraw(false);// view不自己繪制自己

◆setHorizontalScrollBarEnabled(false);// 不設置水平滾動條

◆setVerticalScrollBarEnabled(false);// 不設置垂直滾動條

3. setService 是設置宿主輸入法。

4. computeHorizontalScrollRange ,表示這個view的水平滾動區(qū)域,返回的是候選視圖的總體寬度。

5. onMeasure ,重載自view類,在布局階段被父視圖所調用。比如當父視圖需要根據其子視圖的大小來進行布局時,就需要回調這個函數來看該view的大小。當調用這個函數時必須在內部調用setMeasureDimension來對寬和高進行保存,否則將會有異常出現。這里重載它是為了系統(tǒng)檢測要繪制的字符區(qū)的大小,因為字體可能有大小,應根據字體來。它首先計算自己的期望的寬度,調用resolveSize來看是否能夠得到50px的寬度;然后是計算想要的高度,根據字體和顯示提示區(qū)的padding來確定。

6. onDraw ,view的主要函數,每個view都必須重寫這個函數來繪制自己。它提供了一塊畫布,如果為空,則直接調用父類來畫。

在這里的內部邏輯大概如下:

判斷是否有候選詞,沒有的話就不用繪制。

初始化背景的填充區(qū)域,直接view的背景中得到即可。

對于每一個候選詞,得到其文本,然后計算其寬度,然后再加上兩邊的空隙。

判斷是否選擇了當前詞:觸摸的位置+滾動了的位置。如果是在當前詞的左邊到右邊之間,則將高亮區(qū)域繪制在畫布上面,高亮區(qū)域設置的大小即為當前詞的大小,并且保存被選詞的索引。

將文本繪制在這個候選詞的畫布上面,它進行了一個判斷,判斷哪個才是推薦詞。默認情況下是候選詞的***個詞,但是它判斷***個詞是否是合法的,如果是,則***個詞是候選詞,否者第二個詞才是候選粗,然后進行繪制。

繪制一條線,來分割各個候選詞。上面提到的總共的寬度在所有的詞都繪制出來之后,就能夠得到了。

判斷目標滾動是否是當前的,不是就需要滾動過去。

7. scrollToTarget ,滾到到目標區(qū)域。得到當前值,然后加上一個滾動距離,看是否超過并進行相應調整,之后滾動到相應坐標。

8. setSuggestions ,設置候選詞,之后進行繪制。

9. onTouchEvent ,觸摸事件產生時調用。首先判斷是否為gesturedetector監(jiān)聽的動作,如果不是就進行下面處理。初始化動作,把發(fā)生的動作記錄下來,點觸的坐標也記錄下來。然后,根據動作類型分類反應:

◆向下:沒動作;

◆移動:如果是向左移動就要手動的選擇候選詞;

◆向上:需要手動選擇候選詞。

10. takeSuggestionAt ,選擇在坐標x處的詞,這個處理的是用戶輕輕點擊鍵盤,也就是選擇候選詞。

11. removeHighlight ,去除高亮顯示。

(五)SoftKeyboard.java

整個輸入法的總體的框架,包括什么時候創(chuàng)建,什么時候顯示輸入法,和怎樣和文本框進行通訊等等。上面的文件,都是為了這個類服務的。總體來說,一個輸入法需要的是一個輸入視圖,一個候選詞視圖,還有一個就是和應用程序的鏈接。

基本時序圖如下:

 基本時序圖

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

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

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

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

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

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

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

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

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

五、輸入法調試

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

這里使用Eclipse的DDMS透視圖進行調試,具體介紹參考《用Eclipse開發(fā)和調試Android應用程序 》

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

  DDMS模式

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

  debug模式

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

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

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

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

六、輸入法的調用

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

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

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

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

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

  1. public class MyView extends XXView ...{   
  2.  
  3. //得到InputMethodManager   
  4.  
  5. InputMethodManager input = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);   
  6.  
  7. //定義事件處理器   
  8.  
  9. ResultReceiver receiver = new ResultReceiver(new Handler() {   
  10.  
  11. public void handleMessage(Message msg) {   
  12.  
  13. }   
  14.  
  15. });   
  16.  
  17. ...   
  18.  
  19. //在你想呼出輸入法的時候,調用這一句   
  20.  
  21. input.showSoftInput(this0, mRR);   
  22.  
  23. ...   
  24.  
  25. @Override   
  26.  
  27. //這個方法繼承自View。把自定義的BaseInputConnection通道傳遞給InputMethodService   
  28.  
  29. public InputConnection onCreateInputConnection(EditorInfo outAttrs) {   
  30.  
  31. return new MyBaseInputConnection(thisfalse);   
  32.  
  33. }   
  34.  
  35. }   

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

【編輯推薦】

  1. Android用戶界面設計:布局基礎
  2. Android用戶界面設計:線性布局
  3. Android用戶界面設計:基本按鈕
責任編輯:佚名 來源: iteye
相關推薦

2011-09-08 13:11:07

Android Wid實例

2013-01-06 12:23:59

Android開發(fā)SQLite數據庫

2013-05-21 11:26:49

Android游戲開發(fā)Sensor感應

2013-05-21 09:56:15

2010-08-04 10:17:17

Android開發(fā)WebView組件

2013-05-20 17:51:47

Android游戲開發(fā)SurfaceView

2011-02-28 13:04:27

RelativeLayAndroid Wid

2011-08-02 11:07:42

iOS開發(fā) UIWebView

2011-07-28 10:11:54

iPhone開發(fā) 備忘

2009-06-15 15:16:00

netbeans sw平臺開發(fā)

2013-05-20 17:13:17

Android游戲開發(fā)CanvasPaint

2013-05-20 17:33:44

Android游戲開發(fā)自定義View

2011-09-07 17:54:40

Android Wid開發(fā)

2013-02-20 15:29:00

JSONAndroid開發(fā)

2010-07-13 09:02:19

Widget開發(fā)

2011-09-09 20:14:58

Android Wid

2011-08-22 13:46:15

iPhone開發(fā)GameKit 藍牙

2009-12-23 10:33:30

Silverlight

2009-09-07 06:18:57

C#窗體設計器

2009-08-31 09:41:05

C#反射靜態(tài)方法開發(fā)
點贊
收藏

51CTO技術棧公眾號

国产亚洲综合色| 日本久久精品| 欧美色道久久88综合亚洲精品| 好吊色欧美一区二区三区| 无码日韩精品一区二区| 99精品美女| 日韩av在线精品| 污污网站免费看| 大香伊人中文字幕精品| 久久久久国色av免费看影院| 91欧美日韩一区| 日韩免费一级片| 日韩精品午夜| 日韩黄色av网站| 久久精品国产露脸对白| 欧美调教sm| 亚洲女人****多毛耸耸8| 久久国产一区二区| 99在线观看免费| 久久久999| 欧美日本中文字幕| 极品蜜桃臀肥臀-x88av| 露出调教综合另类| 91精品国产aⅴ一区二区| 免费日韩视频在线观看| 欧美xxxx性xxxxx高清| 国产精品网站在线播放| 欧美乱偷一区二区三区在线| 超碰免费在线97| 免播放器亚洲一区| 欧美最顶级丰满的aⅴ艳星| 国产真实乱人偷精品视频| 婷婷久久一区| 最近2019中文字幕大全第二页| 日韩www视频| 高潮按摩久久久久久av免费| 欧美一级在线视频| 亚洲涩涩在线观看| 最新日韩一区| 色婷婷综合在线| 999一区二区三区| av大全在线| 中文字幕中文乱码欧美一区二区| 午夜精品电影在线观看| 可以在线观看的av| 久久夜色精品国产噜噜av| 国产精品一区二区免费| 午夜免费福利视频| 国产黄色91视频| 亚洲a在线播放| 国产又粗又大又黄| 国产一区二区三区四区在线观看| 国产美女久久精品香蕉69| 五月天婷婷久久| 国产精品毛片一区二区三区| 韩国国内大量揄拍精品视频| 国产主播在线播放| 一区二区三区成人精品| 欧美亚洲国产成人精品| 亚洲伊人成人网| 国产精品日韩久久久| 欧美一区二区色| 欧美性猛交bbbbb精品| 免费日韩av| 国产精品99久久久久久白浆小说 | 亚洲一二三专区| 污污污污污污www网站免费| 久久五月精品中文字幕| 亚洲不卡在线观看| 日韩欧美视频网站| abab456成人免费网址| 欧美另类高清zo欧美| 性欧美在线视频| 另类视频一区二区三区| 欧美成人官网二区| 久久久久麻豆v国产精华液好用吗| 卡通动漫国产精品| 一本久久综合亚洲鲁鲁| 日本女人性生活视频| 欧美成人日韩| 日本aⅴ大伊香蕉精品视频| 夜夜狠狠擅视频| 国产成人综合在线观看| 久久久久久久久久码影片| 成人免费高清在线播放| 亚洲精品成人精品456| 欧美在线一区视频| 国产综合色激情| 亚洲第一男人av| 国产调教在线观看| 欧美理论在线| 国产精品狠色婷| 黄色av一区二区三区| 久久久久久一级片| 精品国产无码在线| 国模套图日韩精品一区二区| 欧美日韩午夜精品| 午夜久久久久久久| 久久久久国产精品| 茄子视频成人在线| 亚洲精品成人电影| 日本一区二区动态图| 男人的天堂avav| 粉嫩91精品久久久久久久99蜜桃| 精品国精品国产尤物美女| 亚洲午夜精品久久久久久高潮| 欧美在线亚洲综合一区| 国产精品久久久久久久app| 人妻无码中文字幕| 亚洲欧美在线高清| 99视频精品免费| 成人激情自拍| 久久综合久久八八| 天天爱天天做天天爽| 国产成人av电影在线播放| 亚洲春色综合另类校园电影| 欧美xxxx视频| 欧美一区二区网站| 少妇高潮惨叫久久久久| 蜜桃av综合| 精品伦精品一区二区三区视频| 搞黄网站在线观看| 欧美日韩国产在线播放网站| 91网站免费视频| 国产欧美成人| 国产亚洲精品自在久久| 国产不卡在线| 欧美疯狂性受xxxxx喷水图片| 亚洲精品国产精品国自产网站| 亚洲三级色网| 国产日韩欧美二区| 日本无删减在线| 日韩美女视频在线| 69av.com| 国产乱色国产精品免费视频| 自拍偷拍一区二区三区| 成人午夜一级| 深夜福利91大全| 一级黄色片在线看| 日韩一区在线看| 午夜精品久久久久久久99热影院| 欧美日韩激情在线一区二区三区| 欧洲成人在线视频| 黄色片在线免费观看| 日韩欧美高清视频| 国产精品无码久久久久一区二区| 国产亚洲在线观看| 蜜桃视频在线观看91| 美女一区网站| 亚洲小视频在线| 欧美另类高清videos的特点| 国产精品天美传媒| 不卡的av中文字幕| 亚洲草久电影| 成人免费视频视频在| 国产www视频在线观看| 精品成人一区二区三区四区| 精品成人免费视频| 99国产欧美另类久久久精品| 国产肥臀一区二区福利视频| 久久99免费视频| 国产精品pans私拍| 午夜在线小视频| 日韩一级片在线观看| 精品一区免费观看| 久久精品在线观看| www.国产福利| 黄色国产精品| 欧美一区二区三区免费在线看| 国产偷久久久精品专区| 色呦呦在线资源| 亚洲国产欧美精品| 综合久久中文字幕| 亚洲日本电影在线| 国产精品久久久久久亚洲av| 国产精品社区| 亚洲欧洲国产日韩精品| 日韩欧美中文在线观看| 2019av中文字幕| 在线观看免费黄视频| 欧美成人a∨高清免费观看| 国产一级做a爱片久久毛片a| 国产精品网站一区| 大尺度做爰床戏呻吟舒畅| 麻豆亚洲精品| 色一情一乱一乱一区91| 久久精品66| 国产日韩专区在线| gogo高清午夜人体在线| 最新国产精品亚洲| 人妻一区二区三区免费| 欧洲亚洲精品在线| 国产一级片视频| 国产精品系列在线| 欧美一区二区免费在线观看| 美女脱光内衣内裤视频久久网站 | 羞羞网站在线免费观看| 国产丝袜精品视频| 国产免费黄色网址| 日韩欧美国产高清91| 久久久精品人妻一区二区三区四| 国产夜色精品一区二区av| 日本久久久久久久久久| 久久精品av麻豆的观看方式| 日本中文字幕网址| 亚洲不卡av不卡一区二区| 欧美日韩一区综合| 999久久久精品一区二区| 国产精品一香蕉国产线看观看| 国产极品人妖在线观看| 久久精品国产91精品亚洲| 日韩av成人| 精品国产一区久久| 国产精品久久久国产盗摄| 色老汉一区二区三区| 国产极品在线播放| 亚洲精品成人在线| 日本 欧美 国产| 国产日韩欧美精品一区| 麻豆精品国产传媒av| 国产福利一区二区三区视频 | 国产传媒一区在线| 天堂av手机在线| 蜜桃一区二区三区在线| www.四虎成人| 国产精品美女| 无码专区aaaaaa免费视频| 欧美一区国产在线| 一区二区三区我不卡| 欧美军人男男激情gay| 欧美成人一区二区在线| 麻豆一区二区| 国产美女99p| 精品国内亚洲2022精品成人| 电影午夜精品一区二区三区| 不卡的国产精品| 国产有码在线一区二区视频| 日韩av超清在线观看| 日本在线精品视频| 欧美电影网站| 亲爱的老师9免费观看全集电视剧| 黄色漫画在线免费看| 91国产精品91| 成人午夜视屏| 国产精品久久久久高潮| 亚洲爱爱视频| 国产精品一区二区久久久| 久久亚洲人体| 91美女福利视频高清| 精品一区二区三区中文字幕在线| 亚洲xxxxx性| 成人资源在线| 精品婷婷色一区二区三区蜜桃| 日韩黄色网络| 日韩女优中文字幕| 色小子综合网| 免费观看国产视频在线| 黄色成人在线网站| 免费无码不卡视频在线观看| 久久性天堂网| 羞羞的视频在线| 国产精品66部| 国产熟女高潮一区二区三区| 久久久99久久| 久久成人小视频| 亚洲国产精品麻豆| www五月天com| 欧美精品第一页| 狠狠人妻久久久久久综合麻豆| 亚洲国产美女久久久久| 国产三级在线看| 草民午夜欧美限制a级福利片| 成人超碰在线| 国产精品久久综合av爱欲tv| 成人动漫视频在线观看| 国产一区二区三区四区五区在线| 久久综合色占| 国产女人18毛片| 欧美一级网站| 特黄视频免费观看| 本田岬高潮一区二区三区| 国产高清一区二区三区四区| 自拍偷拍欧美精品| 成人午夜视频精品一区| 欧美日韩视频专区在线播放| 欧美视频一二区| 在线观看国产欧美| 久草在线资源站资源站| 国产精品白丝jk喷水视频一区| 久久视频社区| 偷拍视频一区二区| 在线精品亚洲| 亚洲天堂国产视频| 久久美女艺术照精彩视频福利播放| 少妇愉情理伦三级| 同产精品九九九| 国产色在线视频| 亚洲图片欧美日产| 18视频在线观看网站| 国产精品99免视看9| av成人资源网| 亚洲欧洲另类精品久久综合| 亚洲欧洲日本mm| 51自拍视频在线观看| 国产午夜精品一区二区三区嫩草 | 色噜噜夜夜夜综合网| 东京干手机福利视频| 色老头一区二区三区| 高清不卡亚洲| 国产亚洲欧美一区二区| 欧美福利专区| 91高清国产视频| 国产亚洲一本大道中文在线| 日韩av电影网址| 欧美一二三在线| 国产在线激情| 国产日韩欧美中文| 精品国产乱码久久久| 女人和拘做爰正片视频| 国产精品1区2区| 日本爱爱小视频| 欧美日韩国产另类不卡| 国产大学生校花援交在线播放 | 99久久伊人精品| 黄色一级片中国| 欧美理论电影在线| 永久免费在线观看视频| 国产精品av电影| 自拍亚洲一区| 丰满少妇被猛烈进入高清播放| 国产成人久久精品77777最新版本| 尤物在线免费视频| 91精品蜜臀在线一区尤物| 在线观看完整版免费| 国产精品狠色婷| 日韩av大片| www.99r| 国产精品天美传媒沈樵| 波多野结衣大片| 国产亚洲视频中文字幕视频| 日韩av超清在线观看| 日韩电影天堂视频一区二区| 先锋a资源在线看亚洲| 瑟瑟视频在线观看| 一本一道波多野结衣一区二区| 人人九九精品| 国产成人久久久| 精品国内自产拍在线观看视频 | 欧美午夜网站| 91视频 - 88av| 东方欧美亚洲色图在线| 亚洲国产精品成人无久久精品| 精品国产免费视频| 在线观看特色大片免费视频| 欧美一区二区三区精美影视| 日韩精品亚洲一区二区三区免费| 88久久精品无码一区二区毛片| 欧美午夜一区二区| 国产原创在线观看| 国产精品视频一区二区三区经| 国产精品普通话对白| 国产成人无码精品久久二区三| 精品视频全国免费看| 好了av在线| 精品国产乱码久久久久久蜜柚| 国产精品一页| 黄色激情小视频| 日韩久久久久久| 日本美女一区| 黄频视频在线观看| 成人免费观看av| 中文字幕手机在线视频| 久久久国产成人精品| 久久男人av| 精品999在线| 亚洲一二三四在线观看| 九色视频在线观看免费播放| 成人a免费视频| 亚洲人成在线影院| 国产精品av久久久久久无| 日韩一区二区在线看片| 蜜桃视频在线观看播放| 色姑娘综合av| 国产69精品久久久久777| 国产99免费视频| 久久国产天堂福利天堂| 国产精品欧美三级在线观看| 亚洲制服中文字幕| 欧美性猛xxx| 综合久久2019| 日韩三级电影| av午夜精品一区二区三区| 6—12呦国产精品| 欧美一区二区色| 欧美片第1页综合| 超薄肉色丝袜一二三| 亚洲国产成人精品一区二区| 成人全视频免费观看在线看| 黄色av网址在线播放| 亚洲视频一区在线观看|