Android事件分發機制
文章目錄
1、概述
本次分享有一個非常重要的概念:
View
,雖然說View
不屬於四大組件,但是它的作用堪比四大組件,甚至比Receiver和Provider的重要性都要大。在Android開發中,Activity承擔這可視化的功能,同時Android系統提供了很多基礎控件,常見的有Button、TextView、CheckBox等。很多時候僅僅使用系統提供的控件是不能滿足需求的,因此我們就需要能夠根據需求進行新控件的定義,而控件的自定義就需要對Android的View體系有深入的理解,只有這樣才能寫出完美的自定義控件。同時Android手機屬於移動設備,移動設備的一個特點就是用戶可以直接通過屏幕來進行一系列操作,一個典型的場景就是屏幕的滑動,用戶可以通過滑動來切換到不同的界面。很多情況下我們的應用都需要支持滑動操作,當處於不同層級的View都可以響應用戶的滑動操作時,就會帶來一個問題,那就是滑動衝突。如何解決滑動衝突呢?這對於初學者來說的確是個頭疼的問題,其實解決滑動衝突本不難,它需要讀者對View的事件分發機制有一定的瞭解,在這個基礎上,我們就可以利於這個特性從而得出滑動衝突的解決方法。
——摘自Android開發藝術探索
2、事件分發概述
事件指的是什麼呢?就是指用戶觸摸屏幕產生的
Touch
事件;在Android中它被封裝成MotionEvent
。
3、常用MotionEvent
分類
- **ACTION_DOWN:**按下View(其他所有事件的開始)。
- **ACTION_UP:**擡起View(與DOWN對應)。
- **ACTION_MOVE:**滑動View。
- **ACTION_CANCEL:**結束事件(非人爲原因)。
其餘事件:
ACTION_MASK
、ACTION_OUTSIDE
、ACTION_POINTER_DOWN
、
ACTION_POINTER_UP
、ACTION_HOVER_MOVE
、ACTION_SCROLL
、
ACTION_HOVER_ENTER
、ACTION_HOVER_EXIT
、ACTION_BUTTON_PRESS
、
ACTION_BUTTON_RELEASE
、ACTION_POINTER_INDEX_MASK
、
ACTION_POINTER_INDEX_SHIFT
;有興趣的可以下來自己瞭解。
3、事件產生順序
4、Android事件扭轉流程
模擬:
經理分派任務,下屬處理這個任務的過程。
-
View層次示例
-
View內部事件處理流程圖(借用郭大神一張圖):
5、事件分發流程及其分析
流程圖及註釋
流程分析
流程1
:在Activity#dispatchTouchEvent返回false/true
當前流程是在Activity#dispatchTouchEvent
攔截並消費事件,不再往下傳遞
03-26 18:54:58.178 com.android.api23 I/com.android.api23.MainActivity: dispatchTouchEvent#event:0
流程2
:在ViewGroup#dispatchTouchEvent返回true:
當前流程是ViewGroup#dispatchTouchEvent
攔截並消費事件,事件不再往下傳遞
03-26 19:08:23.268 com.android.api23 I/com.android.api23.MainActivity: dispatchTouchEvent#event:0
03-26 19:08:23.268 com.android.api23 I/com.android.api23.MyViewGroup: dispatchTouchEvent#event:0
流程3
:在ViewGroup#dispatchTouchEvent返回false:
當前流程是停止往當前ViewGroup
及其子View
事件,並將當前事件交由父類onTouchEvent
處理。
03-26 19:09:15.238 com.android.api23 I/com.android.api23.MainActivity: dispatchTouchEvent#event:0
03-26 19:09:15.238 com.android.api23 I/com.android.api23.MyViewGroup: dispatchTouchEvent#event:0
03-26 19:09:15.238 com.android.api23 I/com.android.api23.MainActivity: onTouchEvent#event:0
流程4
:在ViewGroup#onInterceptTouchEvent返回true:
03-26 19:07:02.918 com.android.api23 I/com.android.api23.MainActivity: dispatchTouchEvent#event:0
03-26 19:07:02.918 com.android.api23 I/com.android.api23.MyViewGroup: dispatchTouchEvent#event:0
03-26 19:07:02.918 com.android.api23 I/com.android.api23.MyViewGroup: onInterceptTouchEvent#event:0
03-26 19:07:02.918 com.android.api23 I/com.android.api23.MyViewGroup: onTouchEvent#event:0
03-26 19:07:02.918 com.android.api23 I/com.android.api23.MainActivity: onTouchEvent#event:0
- 在ViewGroup#onInterceptTouchEvent返回false
當前流程爲系統默認流程即:ViewGroup不攔截事件,事件將往下一級傳遞
03-26 19:06:11.008 com.android.api23 I/com.android.api23.MainActivity: dispatchTouchEvent#event:0
03-26 19:06:11.018 com.android.api23 I/com.android.api23.MyViewGroup: dispatchTouchEvent#event:0
03-26 19:06:11.018 com.android.api23 I/com.android.api23.MyViewGroup: onInterceptTouchEvent#event:0
03-26 19:06:11.018 com.android.api23 I/com.android.api23.MyView: dispatchTouchEvent#event:0
03-26 19:06:11.018 com.android.api23 I/com.android.api23.MyView: onTouchEvent#event:0
03-26 19:06:11.018 com.android.api23 I/com.android.api23.MyViewGroup: onTouchEvent#event:0
03-26 19:06:11.018 com.android.api23 I/com.android.api23.MainActivity: onTouchEvent#event:0
流程5
:在View#dispatchTouchEvent返回true:
當前流程是ViewGroup#dispatchTouchEvent
攔截並消費事件,事件不再往下傳遞
03-26 19:10:41.048 com.android.api23 I/com.android.api23.MainActivity: dispatchTouchEvent#event:0
03-26 19:10:41.048 com.android.api23 I/com.android.api23.MyViewGroup: dispatchTouchEvent#event:0
03-26 19:10:41.048 com.android.api23 I/com.android.api23.MyViewGroup: onInterceptTouchEvent#event:0
03-26 19:10:41.048 com.android.api23 I/com.android.api23.MyView: dispatchTouchEvent#event:0
流程6
:在View#dispatchTouchEvent返回false:
03-26 19:11:36.458 com.android.api23 I/com.android.api23.MainActivity: dispatchTouchEvent#event:0
03-26 19:11:36.458 com.android.api23 I/com.android.api23.MyViewGroup: dispatchTouchEvent#event:0
03-26 19:11:36.458 com.android.api23 I/com.android.api23.MyViewGroup: onInterceptTouchEvent#event:0
03-26 19:11:36.458 com.android.api23 I/com.android.api23.MyView: dispatchTouchEvent#event:0
03-26 19:11:36.458 com.android.api23 I/com.android.api23.MyViewGroup: onTouchEvent#event:0
03-26 19:11:36.458 com.android.api23 I/com.android.api23.MainActivity: onTouchEvent#event:0
流程7
:在View#onTouchEvent返回true:
03-26 19:12:51.688 com.android.api23 I/com.android.api23.MainActivity: dispatchTouchEvent#event:0
03-26 19:12:51.688 com.android.api23 I/com.android.api23.MyViewGroup: dispatchTouchEvent#event:0
03-26 19:12:51.688 com.android.api23 I/com.android.api23.MyViewGroup: onInterceptTouchEvent#event:0
03-26 19:12:51.688 com.android.api23 I/com.android.api23.MyView: dispatchTouchEvent#event:0
03-26 19:12:51.688 com.android.api23 I/com.android.api23.MyView: onTouchEvent#event:0
- 在View#onTouchEvent返回false:
當前流程爲系統默認流程
03-26 19:13:58.188 com.android.api23 I/com.android.api23.MainActivity: dispatchTouchEvent#event:0
03-26 19:13:58.188 com.android.api23 I/com.android.api23.MyViewGroup: dispatchTouchEvent#event:0
03-26 19:13:58.188 com.android.api23 I/com.android.api23.MyViewGroup: onInterceptTouchEvent#event:0
03-26 19:13:58.188 com.android.api23 I/com.android.api23.MyView: dispatchTouchEvent#event:0
03-26 19:13:58.188 com.android.api23 I/com.android.api23.MyView: onTouchEvent#event:0
03-26 19:13:58.188 com.android.api23 I/com.android.api23.MyViewGroup: onTouchEvent#event:0
03-26 19:13:58.188 com.android.api23 I/com.android.api23.MainActivity: onTouchEvent#event:0
流程8
:在ViewGroup#onTouchEvent返回true:
03-26 19:15:14.608 com.android.api23 I/com.android.api23.MainActivity: dispatchTouchEvent#event:0
03-26 19:15:14.608 com.android.api23 I/com.android.api23.MyViewGroup: dispatchTouchEvent#event:0
03-26 19:15:14.608 com.android.api23 I/com.android.api23.MyViewGroup: onInterceptTouchEvent#event:0
03-26 19:15:14.608 com.android.api23 I/com.android.api23.MyView: dispatchTouchEvent#event:0
03-26 19:15:14.608 com.android.api23 I/com.android.api23.MyView: onTouchEvent#event:0
03-26 19:15:14.608 com.android.api23 I/com.android.api23.MyViewGroup: onTouchEvent#event:0
- 在ViewGroup#onTouchEvent返回false:
當前流程爲系統默認流程
03-26 19:16:48.928 com.android.api23 I/com.android.api23.MainActivity: dispatchTouchEvent#event:0
03-26 19:16:48.928 com.android.api23 I/com.android.api23.MyViewGroup: dispatchTouchEvent#event:0
03-26 19:16:48.928 com.android.api23 I/com.android.api23.MyViewGroup: onInterceptTouchEvent#event:0
03-26 19:16:48.928 com.android.api23 I/com.android.api23.MyView: dispatchTouchEvent#event:0
03-26 19:16:48.928 com.android.api23 I/com.android.api23.MyView: onTouchEvent#event:0
03-26 19:16:48.928 com.android.api23 I/com.android.api23.MyViewGroup: onTouchEvent#event:0
03-26 19:16:48.928 com.android.api23 I/com.android.api23.MainActivity: onTouchEvent#event:0
流程9
:在Activity#onTouchEvent返回true:
03-26 19:18:49.648 com.android.api23 I/com.android.api23.MainActivity: dispatchTouchEvent#event:0
03-26 19:18:49.648 com.android.api23 I/com.android.api23.MyViewGroup: dispatchTouchEvent#event:0
03-26 19:18:49.648 com.android.api23 I/com.android.api23.MyViewGroup: onInterceptTouchEvent#event:0
03-26 19:18:49.648 com.android.api23 I/com.android.api23.MyView: dispatchTouchEvent#event:0
03-26 19:18:49.648 com.android.api23 I/com.android.api23.MyView: onTouchEvent#event:0
03-26 19:18:49.648 com.android.api23 I/com.android.api23.MyViewGroup: onTouchEvent#event:0
03-26 19:18:49.648 com.android.api23 I/com.android.api23.MainActivity: onTouchEvent#event:0
- 在Activity#onTouchEvent返回false:
當前流程爲系統默認流程
03-26 19:20:07.738 com.android.api23 I/com.android.api23.MainActivity: dispatchTouchEvent#event:0
03-26 19:20:07.738 com.android.api23 I/com.android.api23.MyViewGroup: dispatchTouchEvent#event:0
03-26 19:20:07.738 com.android.api23 I/com.android.api23.MyViewGroup: onInterceptTouchEvent#event:0
03-26 19:20:07.738 com.android.api23 I/com.android.api23.MyView: dispatchTouchEvent#event:0
03-26 19:20:07.738 com.android.api23 I/com.android.api23.MyView: onTouchEvent#event:0
03-26 19:20:07.738 com.android.api23 I/com.android.api23.MyViewGroup: onTouchEvent#event:0
03-26 19:20:07.738 com.android.api23 I/com.android.api23.MainActivity: onTouchEvent#event:0
AndroidApi23:Android事件分發機制測試Demo