Android 從輸入法 到 EditText 研究


首先看一個 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

欲知詳情請移步至此:點擊打開鏈接


















發佈了72 篇原創文章 · 獲贊 72 · 訪問量 57萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章