事件攔截
主要是View的onInterceptTouchEvent()方法對touch事件進(jìn)行攔截琅捏。
onInterceptTouchEvent:Touch事件攔截方法
圖示:
從外到里的View包含關(guān)系依次為:A->B->C->D
(1)onInterceptTouchEvent()方法對touch事件進(jìn)行攔截,對于嵌套的View吠冤,最先執(zhí)行的是最外層View的onInterceptTouchEvent()方法答朋。然后依次執(zhí)行子視圖的onInterceptTouchEvent()方法,子視圖的子視圖的onInterceptTouchEvent()方法。(這里假設(shè)所有嵌套視圖的onInterceptTouchEvent都會得到執(zhí)行卿樱,即每一個View的onInterceptTouchEvent方法返回都為false的情況)
參照上圖,事件攔截順序:onInterceptTouchEvent執(zhí)行順序依次為:A->B->C->D硫椰,也就是父視圖向子視圖傳遞繁调。
總之,事件攔截機(jī)制是由父視圖開始發(fā)起對事件的攔截(出事了老子先上靶草,兒子稍后)蹄胰。參照上圖當(dāng)手指觸摸事件時(shí),父視圖A首先發(fā)起對該起事件的攔截奕翔,如果A攔截失敗裕寨,就交給它的子視圖B進(jìn)行攔截;如果B攔截失敗就交給B的子視圖C再進(jìn)行攔截..直到某一子視圖對該次事件攔截成功派继。
(2)某一視圖攔截事件成功與否的判斷標(biāo)識是onInterceptTouchEvent方法的返回值宾袜,當(dāng)返回true的時(shí)候說明攔截成功,返回false的時(shí)候說明當(dāng)前視圖對事件攔截失敗驾窟。
也就是說庆猫,只有當(dāng)父視圖的onInterceptTouchEvent返回為false時(shí),事件才向子視圖onInterceptTouchEvent傳遞绅络。返回為true時(shí)月培,表示事件攔截成功,不再向下傳遞恩急,事件交由該View的onTouchEvent方法來處理节视。子視圖的onInterceptTouchEvent不會執(zhí)行。
(3)攔截成功情況
視圖C對當(dāng)前的touch事件攔截成功:此時(shí)意味著C的onInterceptTouchEvent方法返回true假栓,事件將不再向D進(jìn)行傳遞寻行。事件攔截成功后,緊接著需要對攔截的事件進(jìn)行處理匾荆,由視圖C的onTouchEvent方法來執(zhí)行拌蜘。這是不是就意味著當(dāng)前touch事件是由C視圖的onTouchEvent方法來處理的呢?
這要由C視圖的onTouchEvent方法的返回值來決定牙丽。當(dāng)C視圖的onTouchEvent返回true的時(shí)候简卧,當(dāng)前事件就由C全權(quán)處理。
處理的當(dāng)然是事件的各種action烤芦,什么MotionEvent.ACTION_MOVE,ACTION_UP都交給了C的onTouchEvent方法進(jìn)行處理举娩。所以此時(shí)就可以在C的onTouchEvent方法中進(jìn)行switch(event.getAction)判斷執(zhí)行相關(guān)邏輯了。
如果返回的false,說明C視圖對此事件不做處理或者處理不了,怎么辦呢铜涉?兒子不行老爸來智玻,于是事件就交到了B視圖的onTouchEvent方法中。同樣B對此事件處理與否還是看B的onTouchEvent返回值芙代,具體的解釋就跟C一樣了吊奢,不復(fù)多言。
(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)先有子視圖進(jìn)行攔截,處理事件是子視圖優(yōu)先父視圖進(jìn)行處理铺呵。
總結(jié):onInterceptTouchEvent負(fù)責(zé)對事件進(jìn)行攔截裹驰,攔截成功后交給最先遇到onTouchEvent返回true的那個view進(jìn)行處理。
圖解:
一片挂、onInterceptTouchEvent方法返回值情況(此時(shí)默認(rèn)每個onTouchEvent都返回false)
(1)所有ABCD視圖都對該事件不攔截和不處理的情況邦马,當(dāng)傳遞到最末端的子視圖D時(shí)對touch事件進(jìn)行處理,之后事件處理向父視圖傳遞宴卖。(默認(rèn)葉子View是沒有onInterceptTouchEvent方法的滋将,只有onTouchEvent事件進(jìn)行事件處理),也就是所有的onIntercetpTouchEvent方法和onTouchEvent方法都返回false值症昏。
(2)A視圖的onInterceptTouchEvent方法對事件進(jìn)行了攔截随闽,即返回true,則:事件不再向子視圖傳遞肝谭,此時(shí)由A的onTouchEvent方法進(jìn)行事件處理掘宪。
(3)只有B的onInterceptTouchEvent方法對事件進(jìn)行了攔截,即返回true攘烛,則:事件不再向子視圖傳遞魏滚,此時(shí)由B的onTouchEvent方法進(jìn)行事件處理。若此時(shí)B視圖的onTouchEvent方法返回false坟漱,則事件向B的父視圖A傳遞鼠次。
(4)同理,只有C的onInterceptTouchEvent方法對事件進(jìn)行了攔截芋齿,即返回true腥寇,則:事件不再向子視圖傳遞,此時(shí)由C的onTouchEvent方法進(jìn)行事件處理觅捆。若此時(shí)C視圖的onTouchEvent方法返回false赦役,則事件向C的父視圖B傳遞。
二栅炒、onTouchEvent方法返回值情況(此時(shí)默認(rèn)每個onInterceptTouchEvent都返回false掂摔,對事件不攔截)
(1)當(dāng)D的onTouchEvent方法返回true术羔,則表明D對該touch事件全權(quán)處理,事件不再向父視圖傳遞乙漓。
(2)當(dāng)C的onTouchEvent方法返回true级历,則表明D處理不了該事件,交由C對該touch事件全權(quán)處理簇秒,事件不再向父視圖B傳遞。
三秀鞭、dispatchTouchEvent的返回值情況(該方法只有Activity和ViewGroup含有趋观,View不含)
dispatchTouchEvent顧名思義,事件分發(fā)
一般事件分發(fā)锋边,都是從Activity的DispatchTouchEvent收到觸摸事件的Action_down的時(shí)候皱坛,再將事件分發(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都沒被消費(fèi)
(2)a艇棕、ACTION_DOWN被View消費(fèi)了
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://www.reibang.com/p/9f521f34386a
https://blog.csdn.net/xyz_lmn/article/details/12517911