自定義控件之觸摸事件的傳遞

層面優先級:Activity-->ViewGroup-->View

1、dispatchTouchEvent方法:

每個View包括ViewGroup中都能重寫此方法,該方法是用來分發觸摸事件的。是一個佈局中,觸摸事件首先執行的的方法。如果dispatchTouchEvent返回值是true,代表觸摸事件分發給本View的onTouchEvent。如果返回值是false,那麼觸摸事件分發給本View的onInterceptEvent(如果是View,就沒有該方法,那麼事件就到此終止了)。

一般情況下,不建議重寫該方法。


2、Demo介紹,MyLinearLayout繼承了LinearLayout,MyTextView繼承了TextView,佈局如下圖


MyLinearLayout中,重寫了onInterceptTouchEvent和onTouchEvent(dispatchTouchEvent沒有重寫,這個比較容易理解,分析在第一點)。MyTextView中,重寫了onTouchEvent方法(View中沒有onInterceptTouchEvent)。


(1)情況一,MyLinearLayout裏的onInterceptTouchEvent返回默認值(false),MyTextView的onTouchEvent返回true。

觸摸上面的MyTextView部分,結果如下


結論,onInterceptTouchEvent返回false的意思是把觸摸事件往下傳遞給其子View(實際上先抵達子View的dispatchTouchEvent方法,默認返回true),所以即是傳遞給MyTextView的onTouchEvent方法。首先是down從MyLinearLayout的onInterceptTouchEvent傳遞到MyTextView的onTouchEvent,發現onTouchEvent的返回值是true,意思就是說自己消費此觸摸事件,不會往其父MyLinearLayout的onTouchEvent傳遞了。那麼接下來move和up都是按上面的形式傳遞。


(2)情況二,MyLinearLayout裏的onInterceptTouchEvent返回默認值(false),MyTextView的onTouchEvent返回默認值(false),MyLinearLayout裏的onTouchEvent返回true。觸摸上面的MyTextView部分,結果如下。


結論,MyLinearLayout的onInterceptTouchEvent返回false,down事件往下傳遞到MyTextView的onTouchEvent,由於此時false,沒有辦法自己消費此事件,那麼就往其父MyLinearLayout的onTouchEvent裏傳遞了,此時MyLinearLayout的onTouchEvent返回true,代表要自己消費此觸摸事件,所以不會再繼續往上傳了。注意了,後面的move和up會繼續觸發,不過不會再分發給MyLinearLayout的onInterceptTouchEvent了(所以也不可能到MyTextView的onTouchEvent),而是直接到MyLinearLayout的onTouchEvent。(只要onTouchEvent返回true,up事件必然是在這裏完成的)。


(3)情況三,MyLinearLayout裏的onInterceptTouchEvent返回默認值(false),MyTextView的onTouchEvent返回默認值(false),MyLinearLayout裏的onTouchEvent返回false。觸摸上面的MyTextView部分,結果如下。

結論,與情況二的區別在於MyLinearLayout的onTouchEvent返回false。down事件傳到MyLinearLayout的onTouchEvent,返回值是false,然後再往其父的onTouchEvent傳,其後的move和up事件都被onTouchEvent返回值是true的某個父類消費了,類似於情況二,中間的不會傳遞到。


(4)情況四,MyLinearLayout裏的onInterceptTouchEvent返回true,MyLinearLayout裏的onTouchEvent返回true。
觸摸上面的MyTextView部分,結果如下。


結論,MyLinearLayout的onInterceptTouchEvent返回true,觸摸事件不往子View裏傳了,而是傳給自己的onTouchEvent。down事件過來後,返回值是true,那麼就說明了它自己消費了此次的觸摸事件,所以MyLinearLayout的dispatchTouchEvent分發的時候就不再往onInterceptTouchEvent分發了,所以後面的move和up都是直接傳到本View的onTouchEvent。


(5)情況五,MyLinearLayout裏的onInterceptTouchEvent返回true,MyLinearLayout裏的onTouchEvent返回false。

觸摸上面的MyTextView部分,結果如下。


情況五就是情況三和情況四的結合。


--------------------------------------------------以下部分是觸摸MyLinearLayout-------------------------------------------------------------

(6)情況六,MyLinearLayout的onInterceptTouchEvent返回false,MyLinearLayout裏的onTouchEvent返回true

結果如下:


結論,onInterceptTouchEvent無論返回true還是false,結果都是和上面一致。返回false就是給子View的onTouchEvent,由於沒有對MyTextView觸摸,所以此時的子View可以理解爲沒有,那就是本身。而返回true就是傳遞給本View的onTouchEvent。onTouchEvent返回值是true在前面已經分析過了。


(7)情況七,MyLinearLayout的onInterceptTouchEvent返回false,MyLinearLayout裏的onTouchEvent返回false

結果如下:


結論,onInterceptTouchEvent無論返回true還是false,結果都是和上面一致。分析如情況六。onTouchEvent返回值是false在前面已經分析過了。


發佈了41 篇原創文章 · 獲贊 0 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章