Android事件攔截機制

事件攔截

主要是View的onInterceptTouchEvent()方法對touch事件進行攔截。
onInterceptTouchEvent:Touch事件攔截方法

圖示:

從外到里的View包含關系依次為:A->B->C->D

(1)onInterceptTouchEvent()方法對touch事件進行攔截,對于嵌套的View,最先執(zhí)行的是最外層View的onInterceptTouchEvent()方法。然后依次執(zhí)行子視圖的onInterceptTouchEvent()方法,子視圖的子視圖的onInterceptTouchEvent()方法。(這里假設所有嵌套視圖的onInterceptTouchEvent都會得到執(zhí)行,即每一個View的onInterceptTouchEvent方法返回都為false的情況)

參照上圖,事件攔截順序:onInterceptTouchEvent執(zhí)行順序依次為:A->B->C->D,也就是父視圖向子視圖傳遞。

總之,事件攔截機制是由父視圖開始發(fā)起對事件的攔截(出事了老子先上,兒子稍后)。參照上圖當手指觸摸事件時,父視圖A首先發(fā)起對該起事件的攔截,如果A攔截失敗,就交給它的子視圖B進行攔截;如果B攔截失敗就交給B的子視圖C再進行攔截..直到某一子視圖對該次事件攔截成功。

(2)某一視圖攔截事件成功與否的判斷標識是onInterceptTouchEvent方法的返回值,當返回true的時候說明攔截成功,返回false的時候說明當前視圖對事件攔截失敗。

也就是說,只有當父視圖的onInterceptTouchEvent返回為false時,事件才向子視圖onInterceptTouchEvent傳遞。返回為true時,表示事件攔截成功,不再向下傳遞,事件交由該View的onTouchEvent方法來處理。子視圖的onInterceptTouchEvent不會執(zhí)行。

(3)攔截成功情況

視圖C對當前的touch事件攔截成功:此時意味著C的onInterceptTouchEvent方法返回true,事件將不再向D進行傳遞。事件攔截成功后,緊接著需要對攔截的事件進行處理,由視圖C的onTouchEvent方法來執(zhí)行。這是不是就意味著當前touch事件是由C視圖的onTouchEvent方法來處理的呢?

這要由C視圖的onTouchEvent方法的返回值來決定。當C視圖的onTouchEvent返回true的時候,當前事件就由C全權(quán)處理。

處理的當然是事件的各種action,什么MotionEvent.ACTION_MOVE,ACTION_UP都交給了C的onTouchEvent方法進行處理。所以此時就可以在C的onTouchEvent方法中進行switch(event.getAction)判斷執(zhí)行相關邏輯了。

如果返回的false,說明C視圖對此事件不做處理或者處理不了,怎么辦呢?兒子不行老爸來,于是事件就交到了B視圖的onTouchEvent方法中。同樣B對此事件處理與否還是看B的onTouchEvent返回值,具體的解釋就跟C一樣了,不復多言。

(4)攔截失敗情況

如上圖,在A B C D的onInterceptTouchEvent和onTouchEvent都返回false的情況下,方法執(zhí)行的順序依次為A.onInterceptTouchEvent-->B.onInterceptTouchEvent-->C.onInterceptTouchEvent-->D.touchEvent(最深的子視圖沒重寫onInterceptTouchEvent)-->C.touchEvent-->B.touchEvent-->A.touchEvent.

也就是說攔截事件是父視圖優(yōu)先有子視圖進行攔截,處理事件是子視圖優(yōu)先父視圖進行處理。

總結(jié):onInterceptTouchEvent負責對事件進行攔截,攔截成功后交給最先遇到onTouchEvent返回true的那個view進行處理。


圖解:

一、onInterceptTouchEvent方法返回值情況(此時默認每個onTouchEvent都返回false)

(1)所有ABCD視圖都對該事件不攔截和不處理的情況,當傳遞到最末端的子視圖D時對touch事件進行處理,之后事件處理向父視圖傳遞。(默認葉子View是沒有onInterceptTouchEvent方法的,只有onTouchEvent事件進行事件處理),也就是所有的onIntercetpTouchEvent方法和onTouchEvent方法都返回false值。
(2)A視圖的onInterceptTouchEvent方法對事件進行了攔截,即返回true,則:事件不再向子視圖傳遞,此時由A的onTouchEvent方法進行事件處理。
(3)只有B的onInterceptTouchEvent方法對事件進行了攔截,即返回true,則:事件不再向子視圖傳遞,此時由B的onTouchEvent方法進行事件處理。若此時B視圖的onTouchEvent方法返回false,則事件向B的父視圖A傳遞。
(4)同理,只有C的onInterceptTouchEvent方法對事件進行了攔截,即返回true,則:事件不再向子視圖傳遞,此時由C的onTouchEvent方法進行事件處理。若此時C視圖的onTouchEvent方法返回false,則事件向C的父視圖B傳遞。

二、onTouchEvent方法返回值情況(此時默認每個onInterceptTouchEvent都返回false,對事件不攔截)

(1)當D的onTouchEvent方法返回true,則表明D對該touch事件全權(quán)處理,事件不再向父視圖傳遞。
img
(2)當C的onTouchEvent方法返回true,則表明D處理不了該事件,交由C對該touch事件全權(quán)處理,事件不再向父視圖B傳遞。
img

三、dispatchTouchEvent的返回值情況(該方法只有Activity和ViewGroup含有,View不含)

dispatchTouchEvent顧名思義,事件分發(fā)

一般事件分發(fā),都是從Activity的DispatchTouchEvent收到觸摸事件的Action_down的時候,再將事件分發(fā)給ViewGroup的DispatchTouchEvent的。(事件都是從ACTION_DOWN開始的,Activity的dispatchTouchEvent()首先接收到ACTION_DOWN,執(zhí)行super.dispatchTouchEvent(ev),事件向下分發(fā)。)

dispatchTouchEvent()返回true,后續(xù)事件(ACTION_MOVE、ACTION_UP)會再傳遞,如果返回false,dispatchTouchEvent()就接收不到ACTION_UP、ACTION_MOVE。

(1)ACTION_DOWN都沒被消費
(2)a、ACTION_DOWN被View消費了
b、后續(xù)ACTION_MOVE和UP在不被攔截的情況下都會去找VIEW
(3)后續(xù)的被攔截了

Touch事件

android中的Touch事件都是從ACTION_DOWN開始的:
單手指操作:ACTION_DOWN -> ACTION_MOVE -> ACTION_UP
多手指操作:ACTION_DOWN -> ACTION_POINTER_DOWN -> ACTION_MOVE -> ACTION_POINTER_UP -> ACTION_UP.

參考文章:
https://blog.csdn.net/chunqiuwei/article/details/41084921
http://m.itdecent.cn/p/9f521f34386a
https://blog.csdn.net/xyz_lmn/article/details/12517911

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內(nèi)容