首先看一個 View 的一個方法:
View 沒有實現,直接返回 null,
再看 TextView 的實現,
@Override
public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
if (onCheckIsTextEditor() && isEnabled()) {
...
if (mText instanceof Editable) {
InputConnection ic = new EditableInputConnection(this);
outAttrs.initialSelStart = getSelectionStart();
outAttrs.initialSelEnd = getSelectionEnd();
outAttrs.initialCapsMode = ic.getCursorCapsMode(getInputType());
return ic;
}
...
使用了 EditableInputConnection
現在要知道,這個方法何時被調用?
首先我們是點擊了 EditText 系統隨機呼出輸入法,那麼好,我們看 TextView 的 onTouchEvent 方法
@Override
public boolean onTouchEvent(MotionEvent event) {
...
if (touchIsFinished && (isTextEditable() || textIsSelectable)) {
// Show the IME, except when selecting in read-only text.
final InputMethodManager imm = InputMethodManager.peekInstance();
viewClicked(imm);
if (!textIsSelectable && mEditor.mShowSoftInputOnFocus) {
handled |= imm != null && imm.showSoftInput(this, 0);
}<span style="font-family: Arial, Helvetica, sans-serif;"> </span>
這裏調用了 imm.showSoftInput 彈出輸入法,
但是我們還得找到 TextView 與輸入法建立鏈接的地方,我們查找 InputMethodManager 找到了一處調用,view.onCreateInputConnection 方法:
public void restartInput(View view) {
...
boolean startInputInner(IBinder windowGainingFocus, int controlFlags, int softInputMode,
int windowFlags) {
...
// Okay we are now ready to call into the served view and have it
// do its stuff.
// Life is good: let's hook everything up!
EditorInfo tba = new EditorInfo();
tba.packageName = view.getContext().getPackageName();
tba.fieldId = view.getId();
InputConnection ic = view.onCreateInputConnection(tba);
if (DEBUG) Log.v(TAG, "Starting input: tba=" + tba + " ic=" + ic);
...
到這一步似乎 TextView 就與輸入法建立起了連接,不過還有很重要的一點是,要彈出輸入法首先 EditText 必須獲取焦點,正是獲取焦點的時候,與輸入法進行了關鍵一步的交流,這個實現在 View:
protected void onFocusChanged(boolean gainFocus, int direction, Rect previouslyFocusedRect) {
...
InputMethodManager imm = InputMethodManager.peekInstance();
if (!gainFocus) {
if (isPressed()) {
setPressed(false);
}
if (imm != null && mAttachInfo != null
&& mAttachInfo.mHasWindowFocus) {
imm.focusOut(this);
}
onFocusLost();
} else if (imm != null && mAttachInfo != null
&& mAttachInfo.mHasWindowFocus) {
imm.focusIn(this);
}
...
調用了 InputMethodManager 的 focusIn 告知輸入法當前接受輸入的 View,你如果只通過前面幾個方法去看,根本不知道 InputMethodManager 何時確定了 View 對象,
然後,輸入法與接收客戶端進行交互是通過 InputConnection 進行的
public interface InputConnection {
public boolean deleteSurroundingText(int beforeLength, int afterLength); //刪除輸入的字符
public boolean commitText(CharSequence text, int newCursorPosition); //輸入字符
public boolean sendKeyEvent(KeyEvent event); //注入按鍵
}
當你在輸入的時候,輸入法會調用以上3個方法(誇進程)具體如何調用不解釋,本篇的重點在理清聯繫,
除了 EditText ,WebView 也能彈出輸入法,WebView 我是比較好奇的,因爲他只是一個 ViewGroup
欲知詳情請移步至此:點擊打開鏈接