View事件分發機制分析

談到View事件分發,相信大家都不陌生,我也自己琢磨了一下事件分發機制,從源碼分析,提取了關鍵的步驟,並做小小的總結。
主要相關的類與方法爲:
ViewGroup:
dispatchTouchEvent()
onInterceptTouchEvent()
onTouchEvent()

View:
dispatchTouchEvent()
onTouchEvent()

整體的思想可以概括爲:

public boolean dispatchTouchEvent(){
    boolean consume = false;
    if(onInterceptTouchEvent()){
        cousume = onTouchEvent();
    }else{
        consume = child.dispatchTouchEvent();
    }
    return consume;
}

先看整體流程圖:

view事件分發流程圖


修正補充@2016年6月27日:
經@wangmengdeboke 的指出,左下角部分的圖需要做點改動,如下圖所示:
事件分發補充圖
正如補充的,這個disable狀態也是蠻重要的,非常感謝@wangmengdeboke的指正。


  1. activity事件分發
    在圖的左上角,是activity的事件分發,實際是調用DecorView的dispatchTouchEvent來進行的,而DecorView是繼承自FrameLayout的類,其實算是最外層的viewGroup,當事件傳遞到viewGroup,就進入到右邊分支判斷。
  2. ViewGroup的事件分發
    一般情況下,如果不對onInterceptTouchEvent與disallowIntercept進行處理,就會對viewGroup中的childView進行處理,所以這裏可以通過人爲干預達到攔截事件分發的效果,但值得注意的是不能夠攔截down事件,因爲一旦攔截,則在onInterceptTouchEvent中不會接收到up與move事件,即這些事件直接被該viewGroup處理了。
  3. View的事件分發
    當事件分發到view後,會按序執行onTouch,onTouchEvent,onClick【如果有的話】,一旦有一者返回true消耗掉事件,則後者都不會響應,這裏的onTouchEvent,適合做相關的事件處理與執行工作。

總結:
每個手指的動作,都會觸發down,up,move的操作,並引發一系列的事件分發,而且一旦攔截掉down,則所有的事件也會交由該控件處理。在自定義viewGroup與View中,我們可以在onTouchEvent裏面對相關的手指動作做處理,而在ViewGroup中,可以根據需要在onInterceptTouchEvent攔截該攔截需要攔截的事件。在View中,也可以修改父容器disallowInterceptTouchEvent的值達到控制父容器事件分發的目的,不過需要注意的是,down事件一定注意不要被父容器攔截到。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章