Android View事件分發與傳遞

    在Android中,人們主要經過手指與系統交互。Android把全部的touch事件都被封裝成MotionEvent來進行處理,其中包括了手指點擊的位置,時間等信息。其事件類型主要包括:ACTION_DOWN,ACTION_UP,ACTION_MOVE, ACTION_POINTER_DOWN, ACTION_POINTER_UP,ACTION_CANCEL。函數

    這些事件是有觸發順序的,下面舉兩個栗子:spa

  • 只有一個手指點擊在view範圍內,依次觸發的事件:手指按下ACTION_DOWN→手指移動ACTION_MOVE→手指擡起ACTION_UP
  • 多個手指點擊在view範圍內,依次觸發的事件:第一根手指按下ACTION_DOWN→隨後的手指按下ACTION_POINTER_DOWN→有手指擡起ACTION_POINTER_UP→最後一根手指擡起ACTION_UP。

爲了處理這些事件,Android定義了三種方法:blog

  1. dispatchTouchEvent()函數:負責分發傳遞事件,一般不把邏輯處理放在該方法中,因此通常都return super.dispatchTouchEvent().
  2. onInterceptTouchEvent()函數:負責攔截事件
  3. onTouchEvent()函數和 OnTouchListener監聽:負責消費和處理事件

 

事件傳遞流程

        當一個事件被觸發,事件的傳遞從Activity.dispatchTouchEvent()開始,一直從最外層的父view開始向裏面的子view傳遞,直到被攔截。在傳遞過程當中,view能夠經過onInterceptTouchEvent()函數進行攔截,一旦父view攔截了該事件,則再也不向下傳遞事件

        若是被觸發的事件被傳遞至最內層的view,一直未被攔截消費,則會反向向外傳遞,這時候父view能夠經過onTouchEvent函數對事件進行消費,直到activity。另外,若是被觸發的ACTION_DOWN事件在某一層未被消費,那麼接下來的事件是沒法被傳遞進來的。開發

view-ignore-touch-event-example

view-process-touch-event-example

    下面咱們來看幾個例子:it

Case 1  手指點擊在view上,父View(ViewGroup)和View都不消費事件,最終返回給activity消費。io

view1

        以ACTION_DOWN事件爲例,ACTION_DOWN事件沿着圖中黑色箭頭逐層傳遞。在開發過程當中,咱們一般會爲view或者viewGroup設置監聽器來捕獲view事件,listener的onTouch方法會在onTouchEvent以前執行。在分發傳遞過程當中,不管哪一個方法返回true,都表示傳遞中止;若是返回false,則表示繼續傳遞下去。event

        從圖上能夠看出,ACTION_DOWN事件通過activity—>ViewGroup—>View—>ViewGroup—>activity一直未被ViewGroup和View消費處理,又回到了activity中。那麼隨後的ACTION_MOVE和ACTION_UP事件只會沿着綠色箭頭傳遞,再也不沿着ACTION_DOWN事件的路線傳遞了。List

Case 2  手指點擊在父View和子View之間的空隙中,並未點擊在子View上。同上一個例子同樣,ViewGroup中並未消費該事件,返回給了activity。方法

view2

 

        這裏用戶並未點擊到ViewGroup中的view,而是點擊在了ViewGroup和View之間的空隙處。同上一個例子相同,ViewGroup並未處理ACTION_DOWN事件,而是返回給了activity處理。

Case 3  單擊view後,在view中處理消費了ACTION_DOWN事件。

view3

        從圖上能夠看到,ACTION_DOWN事件沿着黑色箭頭方向逐層向內部傳遞,直到在view的onTouchEvent中消費了該事件,並返回true表示再也不向下傳遞。隨後的事件ACTION_MOVE和ACTION_UP將會沿着綠色箭頭傳遞,直到到達view的onTouchEvent方法。

Case 4  單擊view,可是並不在view中處理ACTION_DOWN事件,而是讓它傳遞到ViewGroup中處理。

view4

        ACTION_DOWN事件通過ViewGroup,ViewGroup並未攔截而是傳遞給View。View並未消費該事件而是回傳給了ViewGroup,在ViewGroup中消費該事件。

Case 5  單擊view,在ViewGroup中攔截ACTION_DOWN事件並消費

view5

        ACTION_DOWN事件沿着黑色箭頭分發傳遞,在ViewGroup中對它進行攔截(返回true),因此就再也不繼續向view傳遞ACTION_DOWN事件了。而後在ViewGroup的onTouchEvent方法中消費了該事件,並返回true表示事件已消費。隨後的ACTION_MOVE和ACTION_UP事件將沿着綠色箭頭傳遞,直抵最後的消費方法onTouchEvent,而並不通過攔截事件。

相關文章
相關標籤/搜索