ps: 需要具體源碼分析的童鞋可以轉(zhuǎn)戰(zhàn)原文博客,內(nèi)容十分詳盡,此文為摘錄原文結(jié)論部分,簡明非扼要。
Activity中觸摸事件
相關(guān)API:
- dispatchTouchEvent()和onTouchEvent()
總結(jié):
Activity中的dispatchTouchEvent會將觸摸事件傳遞給Activity所包含的視圖。具體的實現(xiàn)方式在通過調(diào)用到Activity所屬Window的superDispatchTouchEvent,進而調(diào)用到Window的DecorView的superDispatchTouchEvent,進一步的又調(diào)用到ViewGroup的dispatchTouchEvent()。如果Activity所包含的視圖攔截或者消費了該觸摸事件的話,就不會再執(zhí)行Activity的onTouchEvent();如果Activity所包含的視圖沒有攔截或者消費該觸摸事件的話,則會執(zhí)行Activity的onTouchEvent()。
Activity中的onTouchEvent是Activity自身對觸摸事件的處理。如果該Activity的android:windowCloseOnTouchOutside屬性為true,并且當(dāng)前觸摸事件是ACTION_DOWN,而且該觸摸事件的坐標(biāo)在Activity之外,同時Activity還包含了視圖的話;就會導(dǎo)致Activity被結(jié)束。
View中觸摸事件
相關(guān)API:
dispatchTouchEvent()和onTouchEvent()
OnTouchListener, OnClickListener, OnLongClickListener等接口
總結(jié):
View中的dispatchTouchEvent()會將事件傳遞給"自己的onTouch()", "自己的onTouchEvent()"進行處理。而且onTouch()的優(yōu)先級比onTouchEvent()的優(yōu)先級要高。
onTouch()與onTouchEvent()都是View中用戶處理觸摸事件的API。onTouch是OnTouchListener接口中的函數(shù),OnTouchListener接口需要用戶自己實現(xiàn)。onTouchEvent()是View自帶的接口,Android系統(tǒng)提供了默認的實現(xiàn);當(dāng)然,用戶可以重載該API。
onTouch()與onTouchEvent()有兩個不同之處:
onTouch()是View提供給用戶,讓用戶自己處理觸摸事件的接口。而onTouchEvent()是Android系統(tǒng)自己實現(xiàn)的接口。
onTouch()的優(yōu)先級比onTouchEvent()的優(yōu)先級更高。dispatchTouchEvent()中分發(fā)事件的時候,會先將事件分配給onTouch()進行處理,然后才分配給onTouchEvent()進行處理。 如果onTouch()對觸摸事件進行了處理,并且返回true;那么,該觸摸事件就不會分配在分配給onTouchEvent()進行處理了。只有當(dāng)onTouch()沒有處理,或者處理了但返回false時,才會分配給onTouchEvent()進行處理。
ViewGroup中觸摸事件
ViewGroup繼承于View,它中對觸摸事件的處理,很多都繼承于View。但是,ViewGroup又有自己對觸摸事件的特定處理.
相關(guān)API:
ViewGroup重載了dispatchTouchEvent()接口。
ViewGroup新增了onInterceptTouchEvent()接口。
總結(jié):
ViewGroup中的dispatchTouchEvent()會將觸摸事件進行遞歸遍歷傳遞。ViewGroup會遍歷它的所有孩子,對每個孩子都遞歸的調(diào)用dispatchTouchEvent()來分發(fā)觸摸事件。
如果ViewGroup的某個孩子沒有接受(消費或者攔截)ACTION_DOWN事件;那么,ACTION_MOVE和ACTION_UP等事件也一定不會分發(fā)給這個孩子!
ViewGroup的onInterceptTouchEvent()默認返回false。
ViewGroup沒有覆蓋onTouchEvent()。因此,調(diào)用ViewGroup的onTouchEvent()的話;實際上調(diào)用的是它的父類View的onTouchEvent()。
事件分發(fā)案例
??默認分發(fā)觸摸事件??
定義:
自定義一個Activity,該Activity中的顯示內(nèi)容是包含一個自定義的ViewGroup,該ViewGroup中包含一個自定義的View。
- 自定義的Activity-MyActivity
public boolean dispatchTouchEvent(MotionEvent ev): 調(diào)用系統(tǒng)默認的dispatchTouchEvent()
public boolean onTouchEvent(MotionEvent ev): 調(diào)用系統(tǒng)默認的onTouchEvent()
- 自定義ViewGroup-MyViewGroup
public boolean dispatchTouchEvent(MotionEvent ev): 調(diào)用系統(tǒng)默認的dispatchTouchEvent()
public boolean onTouchEvent(MotionEvent ev): 調(diào)用系統(tǒng)默認的onTouchEvent()
public boolean onInterceptTouchEvent(MotionEvent ev):: 調(diào)用系統(tǒng)默認的onInterceptTouchEvent()
- 自定義View-MyView
public boolean dispatchTouchEvent(MotionEvent ev): 調(diào)用系統(tǒng)默認的dispatchTouchEvent()
public boolean onTouchEvent(MotionEvent ev): 調(diào)用系統(tǒng)默認的onTouchEvent()
處理流程圖:

測試流程:
MyActivity收到ACTION_DOWN,進入MyActivity.dispatchTouchEvent()。
MyActivity.dispatchTouchEvent()對ACTION_DOWN觸摸事件進行分發(fā),將消息傳遞給MyViewGroup。即,進入MyViewGroup.dispatchTouchEvent()。
MyViewGroup.dispatchTouchEvent()會調(diào)用MyViewGroup.onInterceptTouchEvent()檢查自己有沒有對觸摸事件進行攔截。即先進入MyViewGroup.onInterceptTouchEvent()。
緊接著,MyViewGroup會退出MyViewGroup.onInterceptTouchEvent()。因為MyViewGroup沒有對觸摸事件進行攔截,MyViewGroup會繼續(xù)分發(fā)事件。
MyViewGroup將觸摸事件分發(fā)給MyView,即進入MyView.dispatchTouchEvent()。
MyView會調(diào)用onTouchEvent()對觸摸事件進行處理,即進入MyView.onTouchEvent() 。
緊接著,MyView會退出MyView.onTouchEvent()。返回false給MyView.dispatchTouchEvent()。
MyView收到MyView.onTouchEvent()的返回值之后,退出MyView.dispatchTouchEvent()。返回false給MyViewGroup的MyViewGroup.dispatchTouchEvent(),表示MyView沒有接受該觸摸事件。
MyViewGroup則得知MyView沒有接受該觸摸事件之后,將自己當(dāng)作一個View,調(diào)用View.dispatchTouchEvent();View.dispatchTouchEvent()接著就會進入MyViewGroup.onTouchEvent()。
緊接著,就會退出MyViewGroup.onTouchEvent()。MyViewGroup.onTouchEvent()沒有消費該觸摸事件,因此返回false。
然后,View.dispatchTouchEvent()就會結(jié)束,并返回false。接著,MyViewGroup就會退出MyViewGroup.dispatchTouchEvent()。并返回false。
MyActivity在得知MyViewGroup沒有接受該觸摸事件之后,就會調(diào)用進入MyActivity.onTouchEvent。
緊接著,就會退出MyActivity.onTouchEvent,并返回false。
至此,MyActivity.dispatchTouchEvent()才結(jié)束。因此,會退出MyActivity.dispatchTouchEvent(),并返回false。
??View接受觸摸事件??
定義:
MyView onTouchEvent() 函數(shù)返回true,其余處理同默認分發(fā)觸摸事件。
處理流程圖:

測試流程
MyActivity收到ACTION_DOWN,進入MyActivity.dispatchTouchEvent()。
MyActivity.dispatchTouchEvent()對ACTION_DOWN觸摸事件進行分發(fā),將消息傳遞給MyViewGroup。即,進入MyViewGroup.dispatchTouchEvent()。
MyViewGroup.dispatchTouchEvent()會調(diào)用MyViewGroup.onInterceptTouchEvent()檢查自己有沒有對觸摸事件進行攔截。即先進入MyViewGroup.onInterceptTouchEvent()。 (04) 緊接著,MyViewGroup會退出MyViewGroup.onInterceptTouchEvent()。因為MyViewGroup沒有對觸摸事件進行攔截,MyViewGroup會繼續(xù)分發(fā)事件.
MyViewGroup將觸摸事件分發(fā)給MyView,即進入MyView.dispatchTouchEvent()。
MyView會調(diào)用onTouchEvent()對觸摸事件進行處理,即進入MyView.onTouchEvent() 。 (07) 緊接著,MyView會退出MyView.onTouchEvent()。此時的,MyView.onTouchEvent()返回的是true;表示MyView消費了此次觸摸事件。
MyView.dispatchTouchEvent()得知MyView.onTouchEvent()消費此次觸摸事件之后;也就返回true,表示MyView接受該此次觸摸事件。
MyViewGroup則得知MyView接受了該觸摸事件之后,就退出MyViewGroup.dispatchTouchEvent(),并返回true。
MyActivity得知MyViewGroup接受了該觸摸事件之后,就會調(diào)用退出MyActivity.dispatchTouchEvent(),并返回true。
結(jié)論:
如果MyView接受了ACTION_DOWN,那么就不會再再執(zhí)行其他對象的onTouchEvent()函數(shù)的。即,不會執(zhí)行MyViewGroup的onTouchEvent()和MyActivity的onTouchEvent()。因為MyView接受了ACTION_DOWN,意味著這個事件已經(jīng)被消費了;就無須其他對象再來消費ACTION_DOWN了。
如果MyView接受了ACTION_DOWN,那么MyView能繼續(xù)收到ACTION_MOVE和ACTION_UP這兩種觸摸觸事件。并且ACTION_MOVE和ACTION_UP的處理流程和ACTION_DOWN的流程基本一樣。
??ViewGroup攔截但不消費觸摸事件??
定義:
MyViewGroup onInterceptTouchEvent() 函數(shù)返回true,其余處理同默認分發(fā)觸摸事件。
處理流程圖:

測試流程
MyActivity收到ACTION_DOWN,進入MyActivity.dispatchTouchEvent()。
MyActivity.dispatchTouchEvent()對ACTION_DOWN觸摸事件進行分發(fā),將消息傳遞給MyViewGroup。即,進入MyViewGroup.dispatchTouchEvent()。
MyViewGroup.dispatchTouchEvent()會調(diào)用MyViewGroup.onInterceptTouchEvent()檢查自己有沒有對觸摸事件進行攔截。即先進入MyViewGroup.onInterceptTouchEvent()。
緊接著,MyViewGroup會退出MyViewGroup.onInterceptTouchEvent()。此時,MyViewGroup.onInterceptTouchEvent()返回true。表示MyViewGroup攔截了該觸摸事件。
MyViewGroup在得知自己攔截了觸摸事件之后,將觸摸事件交給自己的onTouchEvent()進行處理,即進入MyViewGroup.onTouchEvent()。
緊接著,MyViewGroup會退出MyViewGroup.onTouchEvent()。而MyViewGroup自身并沒有消費該事件,因此MyViewGroup.onTouchEvent()返回false。
隨后,退出MyViewGroup.dispatchTouchEvent(),并返回false。表示MyViewGroup沒有接受該觸摸事件。
MyActivity得知MyViewGroup沒有接受該觸摸事件之后,就會調(diào)用進入MyActivity.onTouchEvent()。
緊接著,MyActivity會退出MyActivity.onTouchEvent(),并返回false。表示MyActivity也沒有消費觸摸事件。
最后,MyActivity會退出MyActivity.dispatchTouchEvent(),并返回false。表示此次觸摸事件沒有被消費。
結(jié)論:
MyViewGroup攔截了ACTION_DOWN,并沒有消費該ACTION_DOWN。既然MyViewGroup攔截了ACTION_DOWN,那就意味著該事件就不會分發(fā)給MyViewGroup的子類。但是由于MyViewGroup沒有消費該事件,即它并沒有接受該事件;那么,ACTION_DOWN會繼續(xù)查找其他對象來消費它自己,這也意味著該觸摸事件仍然會發(fā)送MyActivity的onTouchEvent()。如果MyActivity中有和MyViewGroup同級別的GroupView的話,在得知MyViewGroup攔截了ACTION_DOWN,卻沒有消費該ACTION_DOWN之后;MyActivity仍然能夠向這個同級的GroupView分發(fā)消息。
MyViewGroup并沒有消費ACTION_DOWN,那么,MyViewGroup就不能接受到ACTION_MOVE和ACTION_UP這兩種觸摸觸事件。至于MyViewGroup的子類MyView,就更加不可能接受到ACTION_MOVE和ACTION_UP了。
??ViewGroup攔截并消費觸摸事件??
定義:
MyViewGroup onInterceptTouchEvent() 函數(shù)返回true; MyViewGroup onTouchEvent()返回true; 其余處理同默認分發(fā)觸摸事件。
處理流程圖:

測試流程
MyActivity收到ACTION_DOWN,進入MyActivity.dispatchTouchEvent()。
MyActivity.dispatchTouchEvent()對ACTION_DOWN觸摸事件進行分發(fā),將消息傳遞給MyViewGroup。即,進入MyViewGroup.dispatchTouchEvent()。
MyViewGroup.dispatchTouchEvent()會調(diào)用MyViewGroup.onInterceptTouchEvent()檢查自己有沒有對觸摸事件進行攔截。即先進入MyViewGroup.onInterceptTouchEvent()。
緊接著,MyViewGroup會退出MyViewGroup.onInterceptTouchEvent()。此時,MyViewGroup.onInterceptTouchEvent()返回true。表示MyViewGroup攔截了該觸摸事件。
MyViewGroup在得知自己攔截了觸摸事件之后,將觸摸事件交給自己的onTouchEvent()進行處理,即進入MyViewGroup.onTouchEvent()。
緊接著,MyViewGroup會退出MyViewGroup.onTouchEvent(),并返回true。表示MyViewGroup消費了該事件。
隨后,MyViewGroup會退出MyViewGroup.dispatchTouchEvent(),并返回true。表示MyViewGroup接受了該觸摸事件。
MyActivity得知MyViewGroup接受了該觸摸事件之后,就會退出MyActivity.dispatchTouchEvent(),并返回true。表示此次觸摸事件被消費了
結(jié)論:
MyViewGroup攔截并消費了ACTION_DOWN。那么,該事件就不會分發(fā)給MyViewGroup的子類,也不會調(diào)用MyActivity的onTouchEvent()。
MyViewGroup攔截并消費了ACTION_DOWN。那么,MyViewGroup就會接受到ACTION_MOVE和ACTION_UP這兩種觸摸觸事件。而且對于ACTION_MOVE和ACTION_UP事件,不會再執(zhí)行攔截操作,即不會調(diào)用MyViewGroup.onInterceptTouchEvent();而是直接調(diào)用MyViewGroup.onTouchEvent()對事件進行處理。
??ViewGroup沒攔截但是卻消費了觸摸事件??
定義:
MyViewGroup onTouchEvent() 函數(shù)返回true, 其余處理同默認分發(fā)觸摸事件。
處理流程圖:

測試流程
MyActivity收到ACTION_DOWN,進入MyActivity.dispatchTouchEvent()。
MyActivity.dispatchTouchEvent()對ACTION_DOWN觸摸事件進行分發(fā),將消息傳遞給MyViewGroup。即,進入MyViewGroup.dispatchTouchEvent()。
MyViewGroup.dispatchTouchEvent()會調(diào)用MyViewGroup.onInterceptTouchEvent()檢查自己有沒有對觸摸事件進行攔截。即先進入MyViewGroup.onInterceptTouchEvent()。 (04) 緊接著,MyViewGroup會退出MyViewGroup.onInterceptTouchEvent()。此時,MyViewGroup.onInterceptTouchEvent()返回true。表示MyViewGroup攔截了該觸摸事件。
MyViewGroup在得知自己攔截了觸摸事件之后,將觸摸事件交給自己的onTouchEvent()進行處理,即進入MyViewGroup.onTouchEvent()。
緊接著,MyViewGroup會退出MyViewGroup.onTouchEvent(),并返回true。表示MyViewGroup消費了該事件。
隨后,MyViewGroup會退出MyViewGroup.dispatchTouchEvent(),并返回true。表示MyViewGroup接受了該觸摸事件。
MyActivity得知MyViewGroup接受了該觸摸事件之后,就會退出MyActivity.dispatchTouchEvent(),并返回true。表示此次觸摸事件被消費了
結(jié)論:
MyViewGroup沒有攔截卻消費了ACTION_DOWN。由于MyViewGroup沒有攔截ACTION_DOWN,因此,該事件會繼續(xù)分發(fā)給MyViewGroup的子類MyView。由于MyViewGroup消費了ACTION_DOWN,因此該事件不會分發(fā)給MyActivity的onTouchEvent()。
MyViewGroup沒有攔截卻消費了ACTION_DOWN。那么,MyViewGroup仍然可以接受到ACTION_MOVE和ACTION_UP這兩種觸摸觸事件。但是對于MyView而言,由于MyView沒有接受該事件;因此,MyView不會收到ACTION_MOVE和ACTION_UP。