android事件分發

點擊事件會按照 Activity-window-View的順序從上到下依次傳遞,中間會有各種亂七八糟的方法調用,如果最底層也就是View在OnTouchEvent中也返回false時,然後就由Activity處理這次點擊事件,

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);
    }

然後是onUserInteraction()方法,這個方法不是說的重點,雖然它也很重要,有空再說它:

    /**
     * Called whenever a key, touch, or trackball event is dispatched to the
     * activity.  Implement this method if you wish to know that the user has
     * interacted with the device in some way while your activity is running.
     * This callback and {@link #onUserLeaveHint} are intended to help
     * activities manage status bar notifications intelligently; specifically,
     * for helping activities determine the proper time to cancel a notfication.
     *
     * <p>All calls to your activity's {@link #onUserLeaveHint} callback will
     * be accompanied by calls to {@link #onUserInteraction}.  This
     * ensures that your activity will be told of relevant user activity such
     * as pulling down the notification pane and touching an item there.
     *
     * <p>Note that this callback will be invoked for the touch down action
     * that begins a touch gesture, but may not be invoked for the touch-moved
     * and touch-up actions that follow.
     *
     * @see #onUserLeaveHint()
     */
    public void onUserInteraction() {
    }

我們看到在dispatchTouchEvent方法中會先讓Activity的Window處理這個事件,如果一層一層傳下去後,也就是View的OnTouchEvent返回的也是false的話,getWindow().superDispatchTouchEvent(ev)這個方法返回的是false,那麼就讓這個Activity的onTouchEvent處理這個點擊事件。

需要注意的是View並沒有dispatchTouchEvent,因爲View已經是最底層了,沒必要再繼續DispatchTouchEvent了。回到原始的問題,也就是說View的onTouchEvent返回false時,會讓這個View所在的Activity處理這次點擊事件。

然後說下View幾個比較重要的容易混淆的方法先後順序:

這個是在View中定義的一個接口:

    /**
     * Interface definition for a callback to be invoked when a touch event is
     * dispatched to this view. The callback will be invoked before the touch
     * event is given to the view.
     */
    public interface OnTouchListener {
        /**
         * Called when a touch event is dispatched to a view. This allows listeners to
         * get a chance to respond before the target view.
         *
         * @param v The view the touch event has been dispatched to.
         * @param event The MotionEvent object containing full information about
         *        the event.
         * @return True if the listener has consumed the event, false otherwise.
         */
        boolean onTouch(View v, MotionEvent event);
    }

然後是自己的一個私有成員變量:

private OnTouchListener mOnTouchListener;

這個第一個方法,然後View還有個方法onTouchEvent(MotionEvent event):

    /**
     * Implement this method to handle touch screen motion events.
     * <p>
     * If this method is used to detect click actions, it is recommended that
     * the actions be performed by implementing and calling
     * {@link #performClick()}. This will ensure consistent system behavior,
     * including:
     * <ul>
     * <li>obeying click sound preferences
     * <li>dispatching OnClickListener calls
     * <li>handling {@link AccessibilityNodeInfo#ACTION_CLICK ACTION_CLICK} when
     * accessibility features are enabled
     * </ul>
     *
     * @param event The motion event.
     * @return True if the event was handled, false otherwise.
     */
    public boolean onTouchEvent(MotionEvent event) {}

還有個最常用的方法setOnclickListener(OnClickListener l):

    /**
     * Register a callback to be invoked when this view is clicked. If this view is not
     * clickable, it becomes clickable.
     *
     * @param l The callback that will run
     *
     * @see #setClickable(boolean)
     */
    public void setOnClickListener(OnClickListener l) {}

這三個方法的優先級依次是:onTouchListener中的onTouch(View v, MotionEvent event);最高,onTouchEvent(MotionEvent event) {}次之,void onClick(View v);最低。


歡迎有問題的。

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