想必很多android開發(fā)者都遇到過手勢沖突的情況,我們一般都是通過內(nèi)部攔截和外部攔截法解決此類問題。要想搞明白原理就必須了解View的分發(fā)機制骂际。在此之前我們先來了解一下以下三個非常重要的方法:
ViewGroup中有3個:
dispatchTouchEvent()
onInterceptTouchEvent()
onTouchEvent()
View中有2個:
dispatchTouchEvent()
onTouchEvent()
我們分別看看這三個方法:
dispatchTouchEvent()
該方法是用來處理事件的分發(fā)诵叁。如果事件能夠傳遞到當(dāng)前View,那么一定會調(diào)用此方法簿寂。View中該方法的源碼:
代碼比較長漾抬,可以簡化來看:
從以上可以看出,這三個方法的聯(lián)系常遂。
onInterceptTouchEvent()
該方法在上邊可以看出纳令,是在dispatchTouchEvent中調(diào)用,來判斷自己是否需要截取事件克胳,如果該方法返回為true平绩,那么View將消費該事件,即會調(diào)用onTouchEvent()方法漠另。如果返回false,那么通過調(diào)用子View的dispatchTouchEvent()將事件交由子View來處理馒过。
onTouchEvent()
和onInterceptTouchEvent()一樣也是在dispatchTouchEvent中調(diào)用的。用來處理點擊事件酗钞,包括ACTION_DOWN,ACTION_MOVE,ACTION_UP腹忽。如果返回結(jié)果為false表示不消費該事件,并且也不會截獲接下來的事件序列砚作。如果返回為true表示當(dāng)前View消費該事件趟庄。
在這里要強調(diào)View 的OnTouchListener昭卓。如果View設(shè)置了該監(jiān)聽,那么OnTouch()將會回調(diào)。 如果返回為true那么該View的OnTouchEvent將不會在執(zhí)行 這是因為設(shè)置的OnTouchListener執(zhí)行時的優(yōu)先級要比onTouchEvent高羽氮。
還有我們平時很熟悉的onClickListener跳座,其優(yōu)先級比上邊兩個都低。
這三個方法在處理View的沖突時經(jīng)常遇到,所以要熟悉其機制摔竿,看完這三個方法,現(xiàn)在來看看事件分發(fā)機制少孝。
為了能夠清楚的分析继低,我們先新建一個項目,布局如圖:
ViewGroup1嵌套ViewGroup2,然后在嵌套CustomView(這里我繼承自TextView)稍走。布局很簡單袁翁,只是為了說明ViewGroup的分發(fā)過程。然后在相應(yīng)的View中重寫dispatchTouchEvent婿脸,OnInterceptTouchEvent ,OnTouchEvent方法(CustomView沒有OnInterceptTouchEvent)粱胜,并在每個方法中輸出相應(yīng)的Log:
從Log信息可以看出,首先會先執(zhí)行ViewGroup1 dispatchTouchEvent方法狐树,上文中我們講過dispatchTouchEvent()方法的內(nèi)部邏輯:
在ViewGroup1 dispatchTouchEvent方法調(diào)用后焙压,接著會調(diào)用onInterceptTouchEvent()來判斷是否需要截取事件,默認(rèn)是不截取的抑钟。事件會傳遞到ViewGroup1的子View也就是ViewGroup2涯曲。即ViewGroup2 的dispatchTouchEvent方法被調(diào)用,直到CustomView味赃。當(dāng)事件傳遞到CustomView后掀抹,同樣是CustomView的dispatchTouchEvent方法會執(zhí)行虐拓⌒乃祝可以看出,整個事件的分發(fā)是從ViewGroup1向CustomView傳遞的蓉驹。此時如果CustomView 不能處理改事件城榛,也就是說CustomView的OnTouchView方法返回為false,那么事件會向上交給ViewGroup2的OnTouchEvent()事件處理态兴,以此類推:
CustomView的dispatchTouchEvent()沒有執(zhí)行狠持,事件沒有傳遞給CustomView,而是直接調(diào)用了ViewGroup2的ViewGroup2 的onTouchEvent瞻润。
我們會發(fā)現(xiàn)ViewGroup2 的OnTouchEvent不會在執(zhí)行了喘垂,還是用我們剛剛的例子來說,就是員工(CustomView)在接到任務(wù)后順利的完成了任務(wù)绍撞,就不必在勞煩上司響應(yīng)處理了正勒。只有在員工(CustomView)無法完成這項工作時(OnTouchEvent返回為false)時才會請求經(jīng)理幫忙(ViewGroup2 調(diào)用OnTouchEvent方法),同樣的傻铣,如果經(jīng)理也不能搞定的話章贞,就交給老板了。如果有興趣的話非洲,可以去研究研究源碼鸭限。