Android學習之 Touch事件傳遞機制

小呂-ICE發表於2014-08-19

1、基礎知識

(1) 所有Touch事件都被封裝成了MotionEvent物件,包括Touch的位置、時間、歷史記錄以及第幾個手指(多指觸控)等。

 

(2) 事件型別分為ACTION_DOWN, ACTION_UP, ACTION_MOVE, ACTION_POINTER_DOWN, ACTION_POINTER_UP, ACTION_CANCEL,每個事件都是以ACTION_DOWN開始ACTION_UP結束。

 

(3) 對事件的處理包括三類,分別為傳遞——dispatchTouchEvent()函式、攔截——onInterceptTouchEvent()函式、消費——onTouchEvent()函式和OnTouchListener


2、傳遞流程

(1) 事件從Activity.dispatchTouchEvent()開始傳遞,只要沒有被停止或攔截,從最上層的View(ViewGroup)開始一直往下(子View)傳遞。子View可以通過onTouchEvent()對事件進行處理。

 

(2) 事件由父View(ViewGroup)傳遞給子View,ViewGroup可以通過onInterceptTouchEvent()對事件做攔截,停止其往下傳遞。

 

(3) 如果事件從上往下傳遞過程中一直沒有被停止,且最底層子View沒有消費事件,事件會反向往上傳遞,這時父View(ViewGroup)可以進行消費,如果還是沒有被消費的話,最後會到Activity的onTouchEvent()函式。

 

(4) 如果View沒有對ACTION_DOWN進行消費,之後的其他事件不會傳遞過來。

 

(5) OnTouchListener優先於onTouchEvent()對事件進行消費。

 

上面的消費即表示相應函式返回值為true。


3、事件傳遞機制流程圖

(1) View不處理事件流程圖:


                                                                                     view-ignore-touch-event-example


View處理事件流程圖:


                                                                                                   view-process-touch-event-example


(2)事件分發:public boolean dispatchTouchEvent(MotionEvent ev)
當有監聽到事件時,首先由Activity的捕獲到,進入事件分發處理流程。無論是Activity還是View,事件分發自身也具有消費能力。
如果事件分發返回true,表示該事件在本層不再進行分發且已經在事件分發自身中被消費了。至此,事件已經完結。如果你不想Activity中的任何控制元件具有任何的事件消費能力,
最簡答的方法可以重寫此Activity的dispatchTouchEvent方法,直接返回true就ok。
如果事件分發返回 false,表明事件在本層不再繼續進行分發,並交由上層控制元件的onTouchEvent方法進行消費。
當然了,如果本層控制元件已經是Activity,那麼事件將被系統消費或處理。
如果事件分發返回系統預設的 super.dispatchTouchEvent(ev),事件將分發給本層的事件攔截onInterceptTouchEvent 方法進行處理。
<從分析中可以看出,dispatchTouchEvent無論返回true還是false,事件都不再進行分發,只有當其返回super.dispatchTouchEvent(ev),才表明其具有向下層分發的願望>


(3)事件攔截過程:public boolean onInterceptTouchEvent(MotionEvent ev) 

      如果onInterceptTouchEvent返回true,則表示將事件進行攔截,


             並將攔截到的事件交由本層控制元件的onTouchEvent 進行處理;


      如果返回結果是false;則表示不對事件進行攔截,事件得以成功分發到子View。


             並由子View的dispatchTouchEvent進行處理。


      如果返回super.onInterceptTouchEvent(ev),事件預設不會被攔截,


             交由子View的dispatchTouchEvent進行處理。


過程圖如下:




(4)事件響應:public boolean onTouchEvent(MotionEvent ev)
     如果onTouchEvent返回true,表示onTouchEvent處理完事件後消費了此次事件。此時事件終結,將不會進行後續的冒泡 也就是說不會再將事件傳遞到上層View的onTouchEvent處理。
    如果onTouchEvent返回false,事件在onTouchEvent中處理後繼續向上層View冒泡,且有上層View的onTouchEvent進行處理。
    如果返回super.onTouchEvent(ev),則預設處理的邏輯和返回false時相同。





說明:本文轉載自:http://www.trinea.cn/android/touch-event-delivery-mechanism/     

向前輩致敬、向前輩學習... ...


擴充套件:相關閱讀

在ViewGroup中處理Touch Events:

http://yanghui.name/blog/2013/10/17/managing-touch-events-in-a-viewgroup/




相關文章