Android View事件傳遞詳解

Android View事件傳遞


期待與大家共同進步,若有錯誤請指出,謝謝~

blog
github
簡書


事件

View傳遞事件僅指用戶在手機屏幕上的手勢操作,即MotionEvent。其中,最常使用的為ACTION_DOWN(按下手指)、ACTION_MOVE(移動手指)、ACTION_UP(抬起手指)。每個Event事件都是以ACTION_DOWN開始、ACTION_UP結束。Android的UI展示領域可以理解為萬物皆View(ViewGroup是一種特殊的View),View事件傳遞的核心依賴于View的三個方法:

  • dispatchTouchEvent,傳遞事件(true被該對象消費、false其他消費)
  • onInterceptTouchEvent,攔截事件(true攔截、false傳遞)
  • onTouchEvent,消費事件(true消費、false不消費)

其中View只有dispatchTouchEvent事件,沒有onInterceptTouchEvent事件,View的dispatchTouchEvent返回值為true,則代表該View將處理該TouchEvent事件。而Activity也是沒有onInterceptTouchEvent,通過dispatchTouchEvent,如果返回true則代表該touchEvent被消費掉,不繼續(xù)傳遞。

傳遞

  1. 事件由Activity.dispatchTouchEvent開始傳遞,只要沒有被停止或攔截,從最上層的 View(ViewGroup)開始一直往下(子View)傳遞,直至到有被View的onInterceptTouchEvent函數(shù)攔截。
  2. 被攔截后,如果沒有被進行攔截的View通過onTouchEvent消費掉,事件會反向向上傳遞,不需要攔截,直接通過onTouchEvent進行消費。如果沒有被消費掉,則直至傳遞到Activity的onTouchEvent。
  3. 如果View沒有對ACTION_DOWN進行消費,之后的其他事件不會傳遞過來。
  4. OnTouchListener優(yōu)先于onTouchEvent()對事件進行消費。

使用onTouchEvent的返回值來判斷是否該事件被消費掉,返回true代表該事件被該View消費,并且后續(xù)的ACTION_MOVE等操作無需判斷攔截等,直接傳遞給該View進行處理,直至傳入ACTION_UP事件。返回false代表該事件并未被攔截,通過上述邏輯繼續(xù)傳遞事件。

實例

假設布局從外到內(nèi)依次為Layout0、1、2、3
無攔截情況:事件傳遞過程為0 —> 1 —> 2 —> 3 —> 2 —> 1 —> 0
2攔截2消費:事件傳遞過程為0 —> 1 —> 2(消費掉)
2攔截3消費:事件傳遞過程為0 —> 1 —> 2 —> 1 —> 0 (未被消費,ActionDown后續(xù)事件不傳遞)
2攔截1消費:事件傳遞過程為0 —> 1 —> 2 —> 1(消費掉)

總結

通過該View傳遞機制(攔截-消費),可以巧妙組合實現(xiàn)較為特殊的效果。比如,若要實現(xiàn)類似于30s沒有用戶觸摸屏幕則自動觸發(fā)某事件,則可以通過override該Activity的dispatchTouchEvent進行倒計時操作(如果已開始計時,則需要取消掉當前計時)。熟悉了Android中View傳遞機制,目前認為在項目中的幫助主要為2點:

  1. 解決事件沖突,如橫向滑動、縱向滑動以及不同引用第三方控件導致的用戶滑動效果異常等
  2. 實現(xiàn)特殊需求,主要為攔截事件與消費事件的View非同一個,或者說需要觸發(fā)其他方法,如上述的倒計時功能。由于用戶的TouchEvent只能消費一次,需要程序自己設計觸發(fā)額外的方法(事件)。

ThanksTo

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內(nèi)容