天天看點

Android 進階進階 - 觸摸事件傳遞機制

一、觸摸事件的類型

觸摸事件對應的是MotionEvent類,事件類型主要有如下三種

ACTION_DOWN:按下操作

ACTION_MOVE:按下螢幕後滑動操作

ACTION_UP:離開螢幕操作

注:ACTION_DOWN和ACTION_UP這兩個操作是一定存在的,ACTION_MOVE操作是否存在要視情況而定。

二、事件傳遞的三個階段

事件傳遞的三個階段如下:

01、分發(Dispatch)

對應 dispatchTouchEvent 方法,方法原型如下

@Override
    public boolean dispatchTouchEvent(MotionEvent event) {
        return super.dispatchTouchEvent(event);
    }
           

傳回 true 表示事件被目前視圖消費掉;

傳回 super.dispatchTouchEvent(event) 表示繼續分發該事件。

注:如果目前視圖是ViewGroup及其子類,則會調用下面的攔截方法,判斷是否攔截該事件。(原因下面有介紹)

02、攔截(Intercept)

對應 onInterceptTouchEvent 方法,該方法隻存在于ViewGroup 及其子類中,在View 和 Activity 中不存在。方法原型如下:

@Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        return super.onInterceptTouchEvent(ev);
    }
           

傳回 true 表示攔截該事件,同時讓自身的onTouchEvent方法進行消費;

傳回 super.onIntercepTouchEvent(ev)表示不攔截事件,繼續傳遞給子視圖。

03、消費(Consume)

對應 onToouchEvent 方法,方法原型如下:

@Override
    public boolean onTouchEvent(MotionEvent event) {
        return super.onTouchEvent(event);
    }
           

傳回 true 表示目前視圖處理該事件;

傳回 false 表目前視圖不處理該事件,會傳遞給父視圖的 onTouchEvent方法進行處理。

注:在Android 系統中,隻有View、Activity、ViewGroup才有事件傳遞。隻有ViewGroup才有攔截方法。

三、View 的事件傳遞機制

雖然 ViewGroup 是View的子類,但是這裡所說的View 專指除ViewGroup 外的View 控件,如:TextView等 。

結論:

01、觸摸事件從 dispatchTouchEvent 開始,如果無人為幹預(預設傳回super),則事件将從外到内依次傳遞,直到最内層View 的onTouchEvent 處理,傳回true;如果處理不了 傳回 false ,則事件依次向外層傳遞。

02、如果事件向内層傳遞有人為幹預,則事件會提前消費,最内層不會收到事件。

03、View 控件的事件觸發順序,先執行 onTouch 方法,然後才執行 onClick 方法。如果 onTouch 傳回true ,則 onClick 方法不會執行,事件不會繼續傳遞;如果傳回false,則事件繼續傳遞。

四、ViewGroup 的事件傳遞機制

ViewGroup 是作為View控件的容器存在的,如:LinearLayout、ListView等。

結論:

傳遞流程同 View 的事件傳遞,隻是多了onIntercepTouchEvent 方法對事件的攔截,如果傳回 true 攔截事件,不會繼續傳遞;如果傳回 false或者 super 則事件正常傳遞。