Android View事件傳遞
期待與大家共同進步,若有錯誤請指出,謝謝~
事件
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ù)傳遞。
傳遞
- 事件由Activity.dispatchTouchEvent開始傳遞,只要沒有被停止或攔截,從最上層的 View(ViewGroup)開始一直往下(子View)傳遞,直至到有被View的onInterceptTouchEvent函數(shù)攔截。
- 被攔截后,如果沒有被進行攔截的View通過onTouchEvent消費掉,事件會反向向上傳遞,不需要攔截,直接通過onTouchEvent進行消費。如果沒有被消費掉,則直至傳遞到Activity的onTouchEvent。
- 如果View沒有對ACTION_DOWN進行消費,之后的其他事件不會傳遞過來。
- 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點:
- 解決事件沖突,如橫向滑動、縱向滑動以及不同引用第三方控件導致的用戶滑動效果異常等
- 實現(xiàn)特殊需求,主要為攔截事件與消費事件的View非同一個,或者說需要觸發(fā)其他方法,如上述的倒計時功能。由于用戶的TouchEvent只能消費一次,需要程序自己設計觸發(fā)額外的方法(事件)。