Android事件分發之流程分析

原文首發於微信公衆號:躬行之(jzman-blog),歡迎關注交流!

上篇文章中主要針對 Activity、ViewGroup 以及 View 中的相關事件方法進行了基本概述,下面主要以案例的方式對 Android 中的事件傳遞進行歸納。

  1. 默認的事件分發流程
  2. 事件分發
  3. 事件處理
  4. 事件攔截
  5. 總結

閱讀本篇文章之前請先閱讀:

默認的事件分發流程

Android 事件分發的正常流程,也就是默認情況下事件是如何分發的,首先自定義 ViewGroup 和 自定義 View, 如繼承 LinearLayout 自定義 ViewGroup 爲 MLinearLayout,繼承 TextView 自定義 View 爲 MTextView,然後分別重寫各自與事件分發相關的事件方法,Activity 也重寫自己的事件方法,根據日誌觀察正常的事件分發流程,佈局如下圖所示:

通過觸發 MTextView 的 onTouch 事件,對各個事件分發方法都默認處理,執行流程如下圖所示:

顯然,事件分發的起點是 Activity 的 dispatchTouchEvebt() 方法,然後通過一系列動作事件向 ViewGroup 分發,具體表現就是調用 ViewGroup 的 dispatchTouchEvebt() 方法,ViewGroup 的 onInterceptTouchEvent() 方法默認返回 false,也就是默認不攔截事件向子 View(ViewGroup 也是子 View,如 MRelativeLayout),然後,一直向下分發直到最內層的子 View 爲止.

當然,事件分發至子 View , 也就是調用子 View 的 dispatchTouchEvebt() 方法,其事件分發方法內部調用了 onTouchEvent() 方法,onTouchEvent() 默認返回 false,表示該 View 不消費事件,反之返回 true 則消費該事件,下面是根據上述執行結果繪製的默認的事件分發流程,如下圖所示:

通過上面的驗證,至少能夠了解各個事件相關方法的執行順序咯。

事件分發

dispatchTouchEvent() 方法負責事件的分發,決定當前事件是自身消費還是繼續向子 View 分發,返回 true,表示事件已經被消費,後續的事件也會繼續執行,如 ACTION_MOVE、ACTION_UP等事件,返回 false 則繼續向子 View 分發事件,如果是子 View 是 ViewGroup,則先將事件分發給 onInterceptTouchEvent() 方法,從而決定是否攔截該事件。按照上面的案例將 MRelativeLayout 的 dispatchTouchEvent() 方法返回 true ,事件消費且接受之後的一系列事件,日誌截圖如下圖所示:

顯然,當 MRelativeLayout 的 dispatchTouchEvent() 方法返回 true 的時候,事件沒有向下傳遞,這裏爲了更清楚的觀察各個事件方法的執行,具體的事件(如 ACTION_DOWN 等)沒有輸出在日誌中,所以,當 dispatchTouchEvent() 方法返回 true 時表示事件已消費。

事件攔截

onInterceptTouchEvent() 方法負責事件的攔截,其返回值決定是否對當前事件進行攔截,返回值爲 true,表示攔截當前事件,反之不攔截事件,也就是默認實現繼續調用子 View 的 dispatchTouchEvent() 方法進行事件的分發,按照上面的案列將 MRelativeLayout 的 onInterceptTouchEvent() 方法返回值設爲 true,攔截當前事件,使事件不在向下傳遞,日誌截圖如下圖所示:

話說事件攔截之後,那就要進行事件處理了,當然事件處理歸 onTouchEvent() 方法負責,onTouchEvent() 可以處理也可以不處理,如果 onTouchEvent() 返回 true 意味着事件處理完成,返回 false 則事件交由父 View 的 onTouchEvent() 方法進行處理,如圖示情況,MRelativeLayout 攔截了事件,但是沒有處理事件,最終交由 Activity 來處理咯。

事件處理

onTouchEvent() 方法負責事件的處理,其返回值決定是否消費該事件,返回 true 表示當前 View 消費事件,返回 false 表示不消費事件,事件向復 View 的方向傳遞,按照上面的案例將 MRelativeLayout 的 onTouchEvent() 方法返回值設爲 true,日誌截圖如下圖所示:

上面截圖中省略了若干 ACTION_MOVE 事件,當某一 View 事件攔截成功之後,ACTION_DOWN 之後的一系列事件將直接由該 View 處理。

總結

  1. 事件分發由父 View 向子 View 進行事件的分發,在分發過程中如果沒有被攔截和處理,當分發至最深層次的 View 時,將向上回傳事件,最終交由 Activity 進行處理,後續事件也將不會接受;如果中途某個 View 攔截了事件並進行了處理,那麼由攔截事件的 View 的 onTouchEvent() 方法進行處理;如果中途某個 View 攔截了事件並且不進行處理,則事件停止向子 View 分發,然後向父 View 的方向交由父 View 的 onTouchEvent() 方法進行處理;
  2. 事件攔截成功之後則要對事件進行處理,事件的處理主要由攔截事件的 View 的 onTouchEvent() 方法或是其父 View 的 onTouchEvent() 來處理,是否處理具體由相應的 onTouchEvent() 方法的返回值決定;
  3. 事件的處理當然是 onTouchEvent() 方法了,返回 true 表示事件就此處理,反之事件未被處理,繼續向上回傳事件直至被處理。

個人微信公衆號:jzman-blog 可以一起交流學習,可以回覆關鍵字【加羣】邀你入交流羣。

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