Passing path of KeyEvent

    在android中,所有的按键、触屏等事件,都是从顶至下进行分发的。每个ViewGroup子类对象会维持一个Focused变量。它表示在这个控件中具有Focused控件(此控件或是其子控件)。当有按键发生时 会沿着Focuse Path 找到RealFocus 控件(是真正Focused 控件,不是其子控件具有焦点)。同理触屏事件的分发也是如此,只不过和Focuse无关。父控件会遍历所有子控件,看看谁处于触碰事件,并分发给它。

   如果Home key、Menu key,Back Key,Enter key事件(或许还有别的按键)(一些特殊功能的按键,声音等等)发生时 ,会产生一个FINISHED_EVENT 消息,是由InPutMethodManagerService通过AIDL进程调用产生 。
在ViewRoot 中捕获。
       case FINISHED_EVENT:
            handleFinishedEvent(msg.arg1, msg.arg2 != 0);
            break;
    void handleFinishedEvent(int seq, boolean handled) {
        final KeyEvent event = (KeyEvent)retrievePendingEvent(seq);
        if (DEBUG_IMF) Log.v(TAG, "IME finished event: seq=" + seq
                + " handled=" + handled + " event=" + event);
        if (event != null) {
            final boolean sendDone = seq >= 0;
            if (!handled) {
                deliverKeyEventToViewHierarchy(event, sendDone);
                return;
            } else if (sendDone) {
                if (LOCAL_LOGV) Log.v(
                        "ViewRoot", "Telling window manager key is finished");
                try {
                    sWindowSession.finishKey(mWindow);
                } catch (RemoteException e) {
                }
            } else {
                Log.w("ViewRoot", "handleFinishedEvent(seq=" + seq
                        + " handled=" + handled + " ev=" + event
                        + ") neither delivering nor finishing key");
            }
        }
    }

   普通按键 发生时,产生DISPATCH_KEY_FROM_IME 消息 由ViewRoot捕获此消息
        case DISPATCH_KEY_FROM_IME: {
            if (LOCAL_LOGV) Log.v(
                "ViewRoot", "Dispatching key "
                + msg.obj + " from IME to " + mView);
            KeyEvent event = (KeyEvent)msg.obj;
            if ((event.getFlags()&KeyEvent.FLAG_FROM_SYSTEM) != 0) {
                // The IME is trying to say this event is from the
                // system!  Bad bad bad!
                event = KeyEvent.changeFlags(event,
                        event.getFlags()&~KeyEvent.FLAG_FROM_SYSTEM);
            }
            deliverKeyEventToViewHierarchy((KeyEvent)msg.obj, false);
        } break;

上面两大类按键如果预先没有别处理,都会由deliverKeyEventToViewHierarchy(event, sendDone);进行分发。

分发路径:PhoneWindow.DecorView dispatchKeyEvent----》Activity dispatchKeyEvent ----》Window superDispatchKeyEvent --->DecorView superDispatchKeyEvent-->Super dispatchKeyEvent,后续按着 Focus Path分发。如果上述分发中未被处理
会执行Activity dispatchKeyEvent 中的如下代码:
event.dispatch(this, decor != null
                ? decor.getKeyDispatcherState() : null, this);

进一步调用Focus Path中的 View 的 onXXX方法。如果在这些回调方法中,按键未被处理,则进一步由 PhoneWindow.DecorView中dispatchKeyEvent方法的代码
return isDown ? PhoneWindow.this.onKeyDown(mFeatureId, event.getKeyCode(), event)
                    : PhoneWindow.this.onKeyUp(mFeatureId, event.getKeyCode(), event);

处理了:volumn key ,back key 等等按键。

了解了这些就可以游刃有余地截获按键事件。。


“Home key”如果应用程序中没有截获,则最后调用 Activity 中的onBackPressed
默认实现:
    /**
     * Called when the activity has detected the user's press of the back
     * key.  The default implementation simply finishes the current activity,
     * but you can override this to do whatever you want.
     */
    public void onBackPressed() {
        finish();
    }

你可能感兴趣的:(android)