1. 概念
* IMF: 輸入法框架(Input Method Framework)
* IM: 輸入法(Input Method)
* IMS: 輸入法服務(Input Method Service)
* IMMS: 輸入法服務管理器(Input Method Manager Service), system process的一部分,系統中只有一個該服務的實例
* IMM: 輸入法管理器(Input Method Manager), 每個客戶端進程包含一個該實例
* IME: 泛指一個具體的輸入法APK,(Input Method Engine),包括其內部的IMS和各種Binder
2. 核心思想
* 以Service方式運行具體的輸入法
* 在Service中創建輸入法窗口,並把輸入內容傳遞到EditText框中
3. IME兩個Binder
* IMS對應的Binder, IMMS通過該Binder去控制輸入法,如: 顯示、隱藏等
* 專門供客戶端調用的Binder, 該對象用於 在輸入的過程中,客戶端 將事件 傳給輸入法
4. IME幾個要素
4.1 IME 與 EditText框 交互 —— InputConnection
4.2 IME 與 用戶 交互
* InputView: 獲取 用戶輸入
* Candidate View:根據用戶輸入形成候選詞欄 給用戶反饋
5. 動手寫一個IME
* 新建一個工程CarloZ IME, 創建一個Java類 CarloZIME.java, 讓它繼承 InputMethodService;
* 新建一個SettingActivity,作為IME的設定
* 在res/xml 下新建 method.xml, 將下面的代碼 修改以后拷貝進去(im_is_default 默認是true)
<?xml version="1.0" encoding="UTF-8"?> <!-- Copyright (C) 2009 The Android Open Source Project Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --> <!-- The attributes in this XML file provide configuration information --> <!-- for the Search Manager. --> <input-method xmlns:android="http://schemas.android.com/apk/res/android" android:isDefault="@bool/im_is_default" android:settingsActivity="com.carloz.inputmethod.setting.CarloZIMESettingActivity" > </input-method>
* 在AndroidManifest.xml中配置如下
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.carloz.inputmethod"> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme"> <service android:name="com.carloz.inputmethod.CarloZIME" android:label="@string/app_name" android:permission="android.permission.BIND_INPUT_METHOD"> <intent-filter android:priority="1"> <action android:name="android.view.InputMethod" /> </intent-filter> <meta-data android:name="android.view.im" android:resource="@xml/method" /> </service> <activity android:name=".setting.CarloZIMESettingActivity" android:label="@string/title_activity_carlo_zimesetting"> </activity> </application> </manifest>
此時一個最簡單的輸入法就配置完了
問題 1: 如何與EditText框 交互
問題2: 如何獲取用戶輸入
接下來的的我們來解決這倆問題
6. IME 與 EditText交互 —— InputConnection
因為CarloZIME.java繼承了 InputMethodService, 所以它擁有一個方法 getCurrentInputConnection()
前面我們說過,InputConnection 是用來跟 EditText框交互的,說到這里你肯定已經懂了,沒錯,就是這樣
InputConnection ic = getCurrentInputConnection();
ic.commitText("Hello CarloZ", 0);
在合適的地方調用上述代碼,就會向EditText框中 提交 Hello CarloZ 這個字符串。
InputConnection 是一個接口,它與EditText交互的方式可以分為3種: 讀取,插入,替換
(1) 獲取 EditText 框中已有的字符, 方式分為 以相對光標的位置獲取 和 使用絕對位置獲取
* getTextBeforeCursor(n, flag); 獲取光標前面的n個字符
* getTextAfterCursor(n, flag); 獲取光標后面的n個字符
* getExtractedText(request, flags); 獲取當前Edit框所有文字
* setSelection(start, end); 設置絕對位置,從start到end處
* getSelectedText(flags); 獲取絕對區域的文字,該區域由setSelection決定
(2)向EditText框中 添加 或 刪除 字符
* deleteSurroudingText(left, right): 刪除當前光標處 前面left個字符 和 后面 right個字符
* commitText(text, pos); 傳遞text給 EditText, 並且移動 光標到pos處
* commitCompletion(CompletionInfo text); 完成提交,一般是切換到另一個EditText框之前調用,從而使得客戶端在此做點什么
(3)替換 EditText中的字符
* setComposingRegion(start, end); 設置替換區域為 從 start到end處
* setComposingText(text, pos); 把替換區域的文字替換為 text,並把光標移動到pos 處
* finishComposingText(); 可以重復設置替換區域並進行替換,完成后,使用該API 通知客戶端
(4)特殊功能 getCursorCapsMode(reqModes), 用於獲取 當前 光標處的大寫模式
7. 與 用戶交互
現在我們的IME還沒有View, 所以 雖然輸入法在運行,但是你什么都看不到,用戶自然也就無法 輸入任何東西
