天天记录 - Android Touch Event接收并传递给Activity

来源:互联网 发布:网络电视看cctv5的apk 编辑:程序博客网 时间:2024/06/15 07:10



    代码执行堆栈

ViewRootImpl.dispatchMotion
ViewRootImpl.dispatchPointer  (sendMessage)
ViewRootImpl.handleMessage

     @Override    public void handleMessage(Message msg) {         ......          case DISPATCH_POINTER:            deliverPointerEvent((MotionEvent) msg.obj, msg.arg1 != 0);         ......     }


ViewRootImpl.deliverPointerEvent

    private void deliverPointerEvent(MotionEvent event, boolean sendDone) {        if (ViewDebug.DEBUG_LATENCY) {            mInputEventDeliverTimeNanos = System.nanoTime();        }        final boolean isTouchEvent = event.isTouchEvent();        if (mInputEventConsistencyVerifier != null) {            if (isTouchEvent) {                mInputEventConsistencyVerifier.onTouchEvent(event, 0);            } else {                mInputEventConsistencyVerifier.onGenericMotionEvent(event, 0);            }        }        // If there is no view, then the event will not be handled.        if (mView == null || !mAdded) {            finishMotionEvent(event, sendDone, false);            return;        }        // Translate the pointer event for compatibility, if needed.        if (mTranslator != null) {            mTranslator.translateEventInScreenToAppWindow(event);        }        // Enter touch mode on down or scroll.        final int action = event.getAction();        if (action == MotionEvent.ACTION_DOWN || action == MotionEvent.ACTION_SCROLL) {            ensureTouchMode(true);        }        // Offset the scroll position.        if (mCurScrollY != 0) {            event.offsetLocation(0, mCurScrollY);        }        if (MEASURE_LATENCY) {            lt.sample("A Dispatching PointerEvents", System.nanoTime() - event.getEventTimeNano());        }        // Remember the touch position for possible drag-initiation.        if (isTouchEvent) {            mLastTouchPoint.x = event.getRawX();            mLastTouchPoint.y = event.getRawY();        }        // Dispatch touch to view hierarchy.          // 派发Touch Event        boolean handled = mView.dispatchPointerEvent(event);        if (MEASURE_LATENCY) {            lt.sample("B Dispatched PointerEvents ", System.nanoTime() - event.getEventTimeNano());        }        if (handled) {            finishMotionEvent(event, sendDone, true);            return;        }        // Pointer event was unhandled.        finishMotionEvent(event, sendDone, false);    }


mView由PhoneWindow.DecorView实现,即执行PhoneWindow.DecorView.dispatchPointerEvent
     @Override     public boolean dispatchTouchEvent(MotionEvent ev) {          final Callback cb = getCallback();          // cb != null cb就是拥有这个PhoneWindow的Activity          //          return cb != null && !isDestroyed() && mFeatureId < 0 ? cb.dispatchTouchEvent(ev)                    : super.dispatchTouchEvent(ev);     }


Callback就是Activity,通过分析获知以上判断执行cb.dispatchTouchEvent即Activity.dispatchTouchEvent
    /**     * Called to process touch screen events.  You can override this to     * intercept all touch screen events before they are dispatched to the     * window.  Be sure to call this implementation for touch screen events     * that should be handled normally.     *     * @param ev The touch screen event.     *     * @return boolean Return true if this event was consumed.     */    public boolean dispatchTouchEvent(MotionEvent ev) {        if (ev.getAction() == MotionEvent.ACTION_DOWN) {            onUserInteraction();        }        if (getWindow().superDispatchTouchEvent(ev)) {            return true;        }        return onTouchEvent(ev);    }


接着执行 PhoneWindow.superDispatchTouchEvent

     @Override    public boolean superDispatchTouchEvent(MotionEvent event) {        return mDecor.superDispatchTouchEvent(event);    }


执行PhoneWindow.DecorView.superDispatchTouchEvent
     public boolean superDispatchTouchEvent(MotionEvent event) {          return super.dispatchTouchEvent(event);     }


ViewGroup.dispatchTouchEvent 通过UI树,向下传递Touch Event


 Activity.onTouchEvent
     /**     * Called when a touch screen event was not handled by any of the views     * under it.  This is most useful to process touch events that happen     * outside of your window bounds, where there is no view to receive it.     *     * @param event The touch screen event being processed.     *     * @return Return true if you have consumed the event, false if you haven't.     * The default implementation always returns false.     */    public boolean onTouchEvent(MotionEvent event) {        if (mWindow.shouldCloseOnTouch(this, event)) {            finish();            return true;        }               return false;    }