一、首先我們先準備材料,采用最簡單的打Log的方式來進行事件分發(fā)的詳解,其實事件的傳遞機制就是代碼之間的相互調(diào)用。
下面是我準備的activity,view 以及viewGroup中重寫的觸摸時間的三個方法。
分別是
activity中重寫:dispatchTouchEvent(MotionEvent ev)和onTouchEvent(MotionEvent event)這兩個方法,并沒有攔截事件的方法,因為沒有子View。

view中重寫dispatchTouchEvent(MotionEvent ev)和onTouchEvent(MotionEvent event)這兩個方法,并沒有攔截事件的方法,因為view也沒有子view。

viewGroup中重寫三個方法:dispatchTouchEvent(MotionEvent ev)和onTouchEvent(MotionEvent event),dispatchTouchEvent(MotionEvent ev)

以上這些代碼都是采用最原始的返回值 ,只不過是把每個方法的返回值和事件的名稱打印出來了。
以上代碼運行起來的界面結果如下圖所示:

外面紅色的就是我自定義的viewgroup的布局,里面有個綠色的自定義的view的布局,然后點擊綠色的也就是自定義view的區(qū)域,那么重點來了:
① 首先代碼中的什么信息我都不更改,只是把activity中的觸摸事件的方法注釋掉,看一下代碼執(zhí)行的順序。

從上面的截圖中你可以很清楚的看到代碼執(zhí)行的順序,首先執(zhí)行的是viewGroup中的分發(fā)的方法,經(jīng)過點擊這個方法的源碼我們可以知道,在源碼里面調(diào)用了viewGroup的攔截事件的方法,然后攔截事件返回的是false,也就是表明不攔截觸摸事件,然后viewGroup的分發(fā)方法又會調(diào)用view的分發(fā)事件的方法,事件會傳到View的分發(fā)的方法中,然后會調(diào)用view的處理事件的方法,這里,默認的也是返回的false,也就是表明view不處理或者不消費這個觸摸事件。然后viewGroup一看 我艸 子控件不消費這個事件 然后自己看看自己消費不,結果發(fā)發(fā)現(xiàn)自己也不消費,就會傳遞的他自己的上一級,到這里,view和ViewGroup的事件傳遞大概完成了。其實就是一個由外向內(nèi)再由內(nèi)向外的一個傳遞過程。下面的過程類同。
② 我們把activity中注釋掉的代碼去掉 看看代碼執(zhí)行的順序。

③ 我們把view中onTouchEvent(MotionEvent event)的返回值改成true,意思就是讓view消費掉這個事件,看看代碼執(zhí)行的順序。

這個圖中你會看到事被View消費過之后,就不會執(zhí)行viewGroup的消費事件的方法。
④這次我們讓ViewGroup消費掉事件 也就是讓viewGroup的消費事件的方法返回為true

怎么樣,是不是很奇特?
⑤ 這次我們直接讓viewGroup攔截掉事件,也就viewgroup的攔截事件的方法更改為返回true,

這次我們可以看到攔截之后直接回執(zhí)行自己的事件消費方法,結果發(fā)現(xiàn)不消費 則直接返回。
但是需要注意的是,下次再有時間過來的時候,時間就不會傳遞到viewgroup中,這一點好智能?。?!
最后,一張圖總結

最后最后最后的總結-------------------------------------------------------------------------
事件是一組一組的,以DOWN開始,0到n個MOVE,以UP結尾
事件是從外出ViewGroup往內(nèi)層傳遞,如果過程中有控件消費(onTouchEvent),事件不再往下傳遞,如果過程中沒有被消費,事件再依次回傳,最終回傳到Activity中
ViewGroup可以攔截事件,默認5大布局都不攔截事件,如果攔截了事件,調(diào)用自己的onTouchEvent方法,事件不往下傳遞
事件傳遞過程中,如果一個控件在onTouchEvent方法中沒有消費DOWN事件,以后父容器不再給你傳遞任何事件。
如果有什么不對的地方 還望各位提出你寶貴的意見,哈哈哈哈哈哈