Android中觸摸事件傳遞過程當中最重要的是dispatchTouchEvent()、onInterceptTouchEvent()和onTouchEvent()方法。這個是困擾初學者的問題之一,我開始也是。這裏記錄一下dispatchTouchEvent()、onInterceptTouchEvent()和onTouchEvent()的處理過程,以供記憶。html
dispatchTouchEvent是處理觸摸事件分發,事件(多數狀況)是從Activity的dispatchTouchEvent開始的。執行java
super.dispatchTouchEvent(ev),事件向下分發。android
onInterceptTouchEvent是ViewGroup提供的方法,默認返回false,返回true表示攔截。
web
onTouchEvent是View中提供的方法,ViewGroup也有這個方法,view中不提供onInterceptTouchEvent。view中默認返回true,表示消費了這個事件。
函數
View裏,有兩個回調函數 :佈局
public boolean dispatchTouchEvent(MotionEvent ev); public boolean onTouchEvent(MotionEvent ev);
ViewGroup裏,有三個回調函數 :ui
public boolean dispatchTouchEvent(MotionEvent ev); public boolean onInterceptTouchEvent(MotionEvent ev); public boolean onTouchEvent(MotionEvent ev);
public boolean dispatchTouchEvent(MotionEvent ev); public boolean onTouchEvent(MotionEvent ev);
Android中默認狀況下事件傳遞是由最終的view的接收到,傳遞過程是從父佈局到子佈局,也就是從Activity到ViewGroup到View的過程,默認狀況,ViewGroup起到的是透傳做用。Android中事件傳遞過程(按箭頭方向)以下圖,圖片來自[qiushuiqifei],謝謝[qiushuiqifei]整理。spa
觸摸事件是一連串ACTION_DOWN,ACTION_MOVE..MOVE…MOVE、最後ACTION_UP,觸摸事件還有ACTION_CANCEL事件。事件都是從ACTION_DOWN開始的,Activity的dispatchTouchEvent()首先接收到ACTION_DOWN,執行super.dispatchTouchEvent(ev),事件向下分發。
.net
dispatchTouchEvent()返回true,後續事件(ACTION_MOVE、ACTION_UP)會再傳遞,若是返回false,dispatchTouchEvent()就接收不到ACTION_UP、ACTION_MOVE。
code
下面的幾張圖參考自[eoe]
圖1.ACTION_DOWN都沒被消費
圖2-1.ACTION_DOWN被View消費了
圖2-2.後續ACTION_MOVE和UP在不被攔截的狀況下都會去找VIEW
圖3.後續的被攔截了
圖4ACTION_DOWN一開始就被攔截
android中的Touch事件都是從ACTION_DOWN開始的:
單手指操做:ACTION_DOWN---ACTION_MOVE----ACTION_UP
多手指操做:ACTION_DOWN---ACTION_POINTER_DOWN---ACTION_MOVE--ACTION_POINTER_UP---ACTION_UP.