1. 程式人生 > >【Android View】Android中View對觸控事件的處理和傳遞dispatchTouchEvent、onInterceptTouchEvent

【Android View】Android中View對觸控事件的處理和傳遞dispatchTouchEvent、onInterceptTouchEvent

View中存在dispatchTouchEvent、onTouchEvent兩個方法。

而ViewGroup中則存在dispatchTouchEvent、onInterceptTouchEvent、onTouchEvent三個方法。

呼叫順序依次為dispatchTouchEvent——》onInterceptTouchEvent——》onTouchEvent

在Android的View層級觸控體系中,有兩個重要的概念,分別是:分發和攔截

分發

分發可以理解為傳遞,是觸控訊息的一種傳播。

dispatchTouchEvent方法表示分發一個觸控訊息,該方法返回boolean型引數,當返回true時則表示不再向下傳遞和分發該訊息,後續的方法都不會被呼叫,返回false則表示該訊息繼續傳遞和分發。

當手機觸控式螢幕被觸控的時候,父View的dispatchTouchEvent方法會最先被呼叫,如果返回false,則會呼叫該父View的onInterceptTouchEvent方法,並傳遞給子View,如果返回true,則會停止該父View和其子View的一切觸控方法。(也就是不處理這個觸控訊息、常常面試會被問,如何禁止一個介面的所有觸控點選事件,則可以回答在該介面的rootview中實現dispatchTouchEvent並返回true)。

攔截

攔截可以理解為是否在該View中處理該觸控事件。

onInterceptEventTouch方法表示是否攔截該觸控事件,該方法返回boolean型引數,true表示攔截,false表示不攔截。當手機觸控式螢幕被觸控時,父控制元件dispatchTouchEvent方法會通過判斷返回值來決定是否呼叫攔截方法,當決定呼叫的時候,父View的onInterceptEventTouch方法會被呼叫,如果返回true,則會直接呼叫該View的onTouchEvent方法,並直接呼叫該父View的onTouchEvent方法,如果返回false,則會向子View傳遞該訊息,在子View中繼續則判斷dispatchTouchEvent方法,重複上面分發的邏輯。

舉個例子來說明這些。如圖所示,是一個典型的介面層。


其中View A是父View,是個View Group,View B、View D是A的子View,其中View B也是個View Group,View D是個View,View C是B的子View,是個View。

我們都知道,再Android中,View是以樹的形式存在的,所以我們還可以表現為如下形式


根是A,它的子節點有B、D,B有子節點為C。

假設①:我們如果觸控View A,android系統則會呼叫A的dispatchTouchEvent方法,該方法會判斷返回值,如果為true,則止於該方法,剩下的都不會被呼叫,如果返回false,則會呼叫A的onInterceptTouchEvent方法並判斷返回值,如果返回true,則呼叫A的onTouchEvent方法,如果返回false,則會判斷該區域是否有其他子view,發現沒有,則同樣也呼叫A 的onTouchEvent方法。

假設②:我們觸控View D,android系統則會呼叫A的dispatchTouchEvent方法,該方法會判斷返回值,如果為true,則止於該方法,剩下的都不會被呼叫,如果返回false,則會呼叫A的onInterceptTouchEvent方法並判斷返回值,如果返回true,則呼叫A的onTouchEvent方法,如果返回false,則因為該區域還有子節點View D,則會呼叫D的dispatchTouchEvent方法並進行判斷,如果是false,因為D是View,所以不會有onInterceptTouchEvent方法的判斷,會呼叫D的onTouchEvent方法,如果D的onTouchEvent方法返回true,則說明在D上被處理該觸控事件,如果返回false,則會繼續傳遞迴D的父View也就是A,然後呼叫A的onTouchEvent方法,如果D的dispatchTouchEvent返回true,說明該訊息不再分發,則不會呼叫D的剩下的方法,直接找D的父View也就是A,呼叫他的onTouch方法。

假設③:我們觸控View B,android系統則會呼叫A的dispatchTouchEvent方法,該方法會判斷返回值,如果為true,則止於該方法,剩下的都不會被呼叫,如果返回false,則會呼叫A的onInterceptTouchEvent方法並判斷返回值,如果返回true,則呼叫A的onTouchEvent方法,如果返回false,則因為該區域還有子節點View B,則會呼叫B的dispatchTouchEvent方法並進行判斷,如果是false,因為B是ViewGroup,所以會呼叫B的onInterceptTouchEvent方法的判斷,這時因為B是最後一個被觸控的子節點,所以不管是否返回true或者false,B都會攔截該觸控訊息,呼叫B的onTouch,如果B的onTouch返回true,則結束,如果返回false則呼叫B的父節點A的onTouch。


假設④:我們觸控View C,android系統則會呼叫A的dispatchTouchEvent方法,該方法會判斷返回值,如果為true,則止於該方法,剩下的都不會被呼叫,如果返回false,則會呼叫A的onInterceptTouchEvent方法並判斷返回值,如果返回true,則呼叫A的onTouchEvent方法,如果返回false,則因為該區域還有子節點View B,則會呼叫B的dispatchTouchEvent方法並進行判斷,如果是false,因為B是ViewGroup,所以會呼叫B的onInterceptTouchEvent方法的判斷,這時如果返回true,則攔截該方法,呼叫B的onTouch方法,如果B的onTouch返回true,則止於此,如果返回false,則呼叫B的父節點A的onTouch,如果B的onInterceptTouchEvent返回false,則繼續呼叫B的子節點C的dispatchTouchEvent方法,並執行上面說的那些操作。。。

說起來很繞口,但這個例子可以幫助你理解這個觸控邏輯。