快速理解android事件傳遞攔截機制概念

許佳佳233發表於2016-05-30

listview與scollview巢狀使用過的小夥伴一定煩心過其滑動事件的麻煩。

打個比方:

假如有3個佈局,Scollview A ,Scollview B,ListView C,B是A的子部局,C是B的子部局。ABC三者都是垂直滑動,那麼當我觸控手機向下滑動的時候,滑動的是哪個view呢?

倘若明白了android事件分發機制,這些就很容易理解了。 


以下為部分原理:(經常碰到的方法是“事件攔截”和“事件響應”)

ViewGroup中的三個方法:

事件分發(dispatchTouchEvent(MotionEvent ev))

事件攔截(onInterceptTouchEvent(MotionEvent ev))

事件響應(onTouchEvent(MotionEvent ev))

View中只有兩個方法:

事件分發(dispatchTouchEvent(MotionEvent ev))

事件響應(onTouchEvent(MotionEvent ev))


三個方法的呼叫流程大致如下:



看到幾個函式眼花繚亂?完全沒關係!筆者將用更通俗易懂的方式解釋一遍。

我們還是舉一個例子:

LinearLayout A ,Scollview B,ListView C

B是A的子部局,C是B的子部局


當發生觸控事件,事件的分發次序如下:A->B->C

當分發事件結束,事件開始處理,次序如下:C->B->A


在《Android群英傳》中有比較形象的比喻,在此引用一下,希望幫助大家理解:

假設A為總經理,B為部長,C為員工。

一旦有事情,A會通知B,然後B通知C。

事件分發完畢後,從C開始執行。C做完了自己的事情,就通知B,然後B通知A。


那麼再討論一種情況,倘若我只想要第一個A獲取到點選事件,而B和C不用滑動呢

A直接可以在事件分發的時候就 不告訴B和C有這個事件的發生。

也就是最終是:A接收,A不分發事件,A處理事件。


那麼倘若A不僅僅自己要可以獲取到觸控事件,而且還要B可以滾動,但是卻不想要C和B造成滑動衝突呢?

這次就可以讓B不告訴C事件的發生。

最終事件分發次序如下:A->B

事件處理次序如下:B->A


當然還有一種與上述兩種完全不同的情況,我們不希望A的觸控事件執行,但是B和C卻需要獲取到觸控事件。

這次就可以讓B在處理事件之後,不告訴A。

最終事件分發次序如下:A->B->C

事件處理次序如下:C->B



此篇文章更注重概念的理解,如果讀者有興趣,可以再檢視以下兩篇文章。

Android 事件分發

此篇文章使用log列印的方式解釋。

Android事件分發機制完全解析,帶你從原始碼的角度徹底理解(上)

此篇文章從原始碼角度解釋。



相關文章