1. 程式人生 > >Android事件分發完整版總結,終結版解析!

Android事件分發完整版總結,終結版解析!

總體的流程分發
Acticity —–> ViewGroup ——->View
事件分發涉及的幾個方法:
1、dispatchTouchEvent
2、onInterceptTouchEvent
3、onTouchEvent

好多人都是寫個dome,看看日誌。努力的記住,可過不了多長時間就又忘掉了,今天我給大家準備了一個,事件分發的整體流程圖

這裡寫圖片描述

注:仔細看的話,圖分為3層,從上往下依次為Activity、ViewGroup、View。
 事件從左上角那個白色箭頭開始,由Activity的dispatchTouchEvent做分發
 箭頭的上面字代表方法返回值,(return true、return false、return super.xxxxx(),super 的意思是呼叫父類實現。
 dispatchTouchEvent和 onTouchEvent的框裡有個【true---->消費】的字,表示的意思是如果方法返回true,那麼代表事件就此消費,不會繼續往別的地方傳了,事件終止。
 目前所有的圖的事件是針對ACTION_DOWN的,對於ACTION_MOVE和ACTION_UP我們最後做分析。

希望大家多看幾遍這個圖,分發的流程會非常的清晰!

在預設的情況下,分發的流程日誌如下 (此日誌是隻是按下操作)
這裡寫圖片描述
有列印的日誌可以看出,如何子類都不消費事件,最終會交給父類處理這事件。

下面大家在看一下預設的事件分發流程圖(如果事件不被攔截):
這裡寫圖片描述
總結:
1、如果我們沒有對事件做任何攔截的情況,是從Activity —–>ViewGroup —–>View依次從上往下分發的,只到分到View,如果還有處理此事件,那麼會依次View —–>ViewGroup —–>Avtivity 從下往上依次呼叫onTouchEvent方法傳給父類。

2、dispatchTouchEvent 和onTonchEvent事件返回true,那麼就會消費此事件(事件的終止,沒有誰會再接收到此事件)


這裡寫圖片描述

3、dispatchTouchEvent和onTouEvent 返回false,會回到父類的onTouchEvent
這裡寫圖片描述

看上圖深藍色的線,對於返回false的情況,事件都是傳給父控制元件onTouchEvent處理。

*對於dispatchEvent返回false的含義應該是:事件停止往子類分發和開始往父控制元件回溯(父類的onTouchEvent開始從下往上回傳,直至某個onTouchEvent return true ),事件分發就像遞迴,return false的意思就是遞迴等值,然後開始回溯。

*對於onTouchEvent return false 就比較簡單了,它就是不消費此事件,並讓事件繼續往父控制元件的方向從下往上流動

4、onInterceptTouchEvent 的作用

這裡寫圖片描述

Intercept 的意思就攔截,每個ViewGroup每次在做分發的時候,問一問攔截器要不要攔截(也就是問問自己這個事件要不要自己來處理)如果要自己處理那就在onInterceptTouchEvent方法中 return true就會交給自己的onTouchEvent的處理,如果不攔截就是繼續往子控制元件往下傳。預設是不會去攔截的,因為子View也需要這個事件,所以onInterceptTouchEvent攔截器return super.onInterceptTouchEvent()和return false是一樣的,是不會攔截的,事件會繼續往子View的dispatchTouchEvent傳遞。

5、ViewGroup和View的dispachtTouchEvent方法返回super.dispatchTouchEvent()的時候事件流走向。

這裡寫圖片描述

首先看一下ViewGroup的dispachTouEvent時間分發流程,之前說的true是終結的傳遞。return false是回溯到父View的TouchEvent,然後ViewGroup通過怎樣的方法才能傳遞到自己的onTouchEvent,方法只有一種,那就是通過InterceptTouchEvent把事件攔截下來傳給自己的onTouchEvent,所以ViewGroup dispatchTouchEvent方法的super預設實現就是去呼叫onInterceptTouchEvent,記住這一點。 那麼對於View的dispatchTouchEvent return super.dispatchTouchEvent()的時候呢事件會傳到哪裡呢,很遺憾View沒有攔截器。但是同樣的道理return true是終結。return false 是回溯會父類的onTouchEvent,怎樣把事件分發給自己的onTouchEvent 處理呢,那隻能return super.dispatchTouchEvent,View類的dispatchTouchEvent()方法預設實現就是能幫你呼叫View自己的onTouchEvent方法的。

說了這麼多不知道大家明白了沒有,給大家做一個總結:
*對於dispatchTouchEvent、onTouchEvent、return true是終結事件傳遞。return false是回溯到父View的onTouchEvent方法。

*ViewGroup想分發給自己的onTouchEvent,需要onInterceptTouchEvnet攔截到事件 return true,從而傳遞給自己的onTouchEvent總

*ViewGroup的onInterceptTouchEvent預設是不攔截的,所以return super.onInterceptTouchEvent()=return false;

*View沒有攔截器,為了讓View可以把事件分配到自己的onTouchEvent中,View的dispatchTouchEvent預設實現(super)就是把事件分發給自己的onTouchEvent。

ViewGroup和View 的dispatchTouchEvent 是做事件分發,那麼這個事件可能分發出去的四個目標
1、 自己消費,終結傳遞。——->return true ;
2、 給自己的onTouchEvent處理——-> 呼叫super.dispatchTouchEvent()系統預設會去呼叫 onInterceptTouchEvent,在onInterceptTouchEvent return true就會去把事件分給自己的onTouchEvent處理。
3、 傳給子View——>呼叫super.dispatchTouchEvent()預設實現會去呼叫 onInterceptTouchEvent 在onInterceptTouchEvent return false,就會把事件傳給子類。
4、 不傳給子View,事件終止往下傳遞,事件開始回溯,從父View的onTouchEvent開始事件從下到上回歸執行每個控制元件的onTouchEvent——->return false;

ViewGroup和View的onTouchEvent方法是做事件處理的,那麼這個事件只能有兩個處理方式:
1、自己消費掉,事件終結,不在傳給誰。—–>return true
2、繼續從下往上傳,不消費事件,讓父View也能收到到這個事件 —->return false;View的預設實現是不消費的,預設super == false;

ViewGroup的onInterceptTouchEvent方法對於事件有兩種情況:
1、攔截掉此事件,把事件傳給自己的onTouchEvent。—–>return true
2、繼續往下傳,ViewGroup預設是不攔截的,return false == super.onInterceptTouchEvent

關於MOVE 和UP的事件處理

以上講的都是ACTION_DOWN事件的傳遞,因為ACTION_MOVE和ACTION_UP傳遞的事件是不一樣的,你在ACTION_DOWN的時候返回了false,後面一系列其他的action就不會在執行了。簡單的說,就是當dispachTouchEvent在進行事件分發的時候,只有一個事件返回true(ACTION_DOWN)返回true,ACTION_MOVE和ACTION_UP才會收到事件,好多人都這麼說,下面的例子會跟大家證明原因

1、我們在ViewGroup1 的dispatchTouchEvent 方法返回true消費這次事件
ACTION_DOWN 事件從(Activity的dispatchTouchEvent)——–> (ViewGroup1 的dispatchTouchEvent) 後結束傳遞,事件被消費(如下圖紅色的箭頭程式碼ACTION_DOWN 事件的流向)。

//列印日誌
Activity | dispatchTouchEvent --> ACTION_DOWN 
ViewGroup1 | dispatchTouchEvent --> ACTION_DOWN
---->消費

這裡寫圖片描述

在這種場景下ACTION_MOVE和ACTION_UP 將如何呢,看下面的打出來的日誌

    Activity | dispatchTouchEvent --> ACTION_MOVE 
    ViewGroup1 | dispatchTouchEvent --> ACTION_MOVE
    TouchEventActivity | dispatchTouchEvent --> ACTION_UP 
    ViewGroup1 | dispatchTouchEvent --> ACTION_UP

下圖中
紅色的箭頭代表ACTION_DOWN 事件的流向
藍色的箭頭代表ACTION_MOVE 和 ACTION_UP 事件的流向
這裡寫圖片描述

2、我們在ViewGroup2 的dispatchTouchEvent 返回true消費這次事件

Activity | dispatchTouchEvent --> ACTION_DOWN 
ViewGroup1 | dispatchTouchEvent --> ACTION_DOWN
ViewGroup1 | onInterceptTouchEvent --> ACTION_DOWN
ViewGroup2 | dispatchTouchEvent --> ACTION_DOWN
---->消費
Activity | dispatchTouchEvent --> ACTION_MOVE 
ViewGroup1 | dispatchTouchEvent --> ACTION_MOVE
ViewGroup1 | onInterceptTouchEvent --> ACTION_MOVE
ViewGroup2 | dispatchTouchEvent --> ACTION_MOVE

TouchEventActivity | dispatchTouchEvent --> ACTION_UP 
ViewGroup1 | dispatchTouchEvent --> ACTION_UP
ViewGroup1 | onInterceptTouchEvent --> ACTION_UP
ViewGroup2 | dispatchTouchEvent --> ACTION_UP

紅色的箭頭代表ACTION_DOWN 事件的流向
藍色的箭頭代表ACTION_MOVE 和 ACTION_UP 事件的流向

這裡寫圖片描述

3、我們在View 的dispatchTouchEvent 返回true消費這次事件
這個我不就畫圖了,效果和在ViewGroup2 的dispatchTouchEvent return true的差不多,同樣的收到ACTION_DOWN 的dispatchTouchEvent函式都能收到 ACTION_MOVE和ACTION_UP。
所以我們就基本可以得出結論如果在某個控制元件的dispatchTouchEvent 返回true消費終結事件,那麼收到ACTION_DOWN 的函式也能收到 ACTION_MOVE和ACTION_UP。

4、我們在View 的onTouchEvent 返回true消費這次事件
紅色的箭頭代表ACTION_DOWN 事件的流向
藍色的箭頭代表ACTION_MOVE 和 ACTION_UP 事件的流向

這裡寫圖片描述

5、我們在ViewGroup 2 的onTouchEvent 返回true消費這次事件
紅色的箭頭代表ACTION_DOWN 事件的流向
藍色的箭頭代表ACTION_MOVE 和 ACTION_UP 事件的流向
這裡寫圖片描述

6、我們在ViewGroup 1 的onTouchEvent 返回true消費這次事件
紅色的箭頭代表ACTION_DOWN 事件的流向
藍色的箭頭代表ACTION_MOVE 和 ACTION_UP 事件的流向
這裡寫圖片描述

7、我們在Activity 的onTouchEvent 返回true消費這次事件
紅色的箭頭代表ACTION_DOWN 事件的流向
藍色的箭頭代表ACTION_MOVE 和 ACTION_UP 事件的流向
這裡寫圖片描述

8、我們在View的dispatchTouchEvent 返回false並且Activity 的onTouchEvent 返回true消費這次事件
紅色的箭頭代表ACTION_DOWN 事件的流向
藍色的箭頭代表ACTION_MOVE 和 ACTION_UP 事件的流向
這裡寫圖片描述

9、我們在View的dispatchTouchEvent 返回false並且ViewGroup 1 的onTouchEvent 返回true消費這次事件
紅色的箭頭代表ACTION_DOWN 事件的流向
藍色的箭頭代表ACTION_MOVE 和 ACTION_UP 事件的流向

這裡寫圖片描述

10、我們在View的dispatchTouchEvent 返回false並且在ViewGroup 2 的onTouchEvent 返回true消費這次事件
紅色的箭頭代表ACTION_DOWN 事件的流向
藍色的箭頭代表ACTION_MOVE 和 ACTION_UP 事件的流向

這裡寫圖片描述

11、我們在ViewGroup2的dispatchTouchEvent 返回false並且在ViewGroup1 的onTouchEvent返回true消費這次事件
紅色的箭頭代表ACTION_DOWN 事件的流向
藍色的箭頭代表ACTION_MOVE 和 ACTION_UP 事件的流向

這裡寫圖片描述

12、我們在ViewGroup2的onInterceptTouchEvent 返回true攔截此次事件並且在ViewGroup 1 的onTouchEvent返回true消費這次事件。
紅色的箭頭代表ACTION_DOWN 事件的流向
藍色的箭頭代表ACTION_MOVE 和 ACTION_UP 事件的流向

這裡寫圖片描述

一下子畫了好多圖,還有好幾種情況就不再畫了,相信你也看出規律了,對於在onTouchEvent消費事件的情況:在哪個View的onTouchEvent 返回true,那麼ACTION_MOVE和ACTION_UP的事件從上往下傳到這個View後就不再往下傳遞了,而直接傳給自己的onTouchEvent 並結束本次事件傳遞過程。

對於ACTION_MOVE、ACTION_UP總結:ACTION_DOWN事件在哪個控制元件消費了(return true), 那麼ACTION_MOVE和ACTION_UP就會從上往下(通過dispatchTouchEvent)做事件分發往下傳,就只會傳到這個控制元件,不會繼續往下傳,如果ACTION_DOWN事件是在dispatchTouchEvent消費,那麼事件到此為止停止傳遞,如果ACTION_DOWN事件是在onTouchEvent消費的,那麼會把ACTION_MOVE或ACTION_UP事件傳給該控制元件的onTouchEvent處理並結束傳遞。