基本知識
- 每個事件都被封裝成為
,包含了Touch的位置,點按的數量(手指的數量),時間點等資訊MotionEvent
- 包含了使用者的目前動作,主要有以下幾種類型
-
ACTION_DOWN
-
ACTION_UP
-
ACTION_MOVE
-
ACTION_POINTER_DOWN
-
ACTION_POINTER_UP
-
ACTION_CANCEL
-
- Android事件響應涉及的主要方法有以下幾個:
-
用于事件的分發,所有的事件都要通過此方法進行分發,決定是自己對事件進行消費還是交由子View處理.dispatchTouchEvent()
-
主要用于事件的處理,傳回true表示消費目前事件.onTouchEvent()
-
是onInterceptTouchEvent
中獨有的方法,若傳回ViewGroup
表示攔截目前事件,交由自己的true
進行處理,傳回onTouchEvent()
表示不攔截false
-
- 事件被消費的意思是
,dispatchTouchEvent()
,onTouchEvent()
等方法傳回onInterceptTouchEvent()
true
流程
事件由Activity的
dispatchTouchEvent()
開始,将事件傳遞給目前Activity的根View,事件開始自上而下進行傳遞,直至被消費.
事件傳遞至
View
的
dispatchTouchEvent()
時, 首先會判斷
OnTouchListener
是否存在,倘若存在者則由
OnTouchListener
進行消費,執行
onTouch()
,.若
onTouch()
未對事件進行消費,事件将繼續交由
onTouchEvent
處理,通過檢視源碼可知,View的
onClick
事件是在
onTouchEvent
的
ACTION_UP
中觸發的,是以,onTouch事件優先于
onClick
事件.
事件傳遞至
ViewGroup
時,調用
dispatchTouchEvent()
進行處理:
1. 檢查送否應該對事件進行攔截:
onInterceptTouchEvent()
,若為true,跳過2步驟
2. 按照子View添加順序的逆序,将事件依次分發給子View,若事件被前一個View消費了,将不再繼續分發
3. 如果2中沒有子View對事件進行消費或者子View的數量為零,事件的處理流程和View的處理流程一緻
若事件在自上而下的傳遞過程中一直沒有被消費,而且最底層的子View也沒有對其進行消費,事件會反向向上傳遞,此時,父
ViewGroup
可以對事件進行消費,若仍然沒有被消費的話,最後會回到Activity的
onTouchEvent
下面附上整個事件傳遞的流程圖
總結
- 事件總是由
的Activity
開始向下進行傳遞dispatchTouchEvent
- 父View(
)可将事件傳遞給子View,ViewGroup
可将事件攔截,事件将停止向下傳遞(ViewGroup
中傳回onInterceptTouchEvent
)true
- 事件自上而下傳遞,直到被消費
- 如果View或者ViewGroup沒有消費
,其他事件也不會被傳遞進來ACTION_DOWN
- 所有未被消費的事件将會回傳至Activity的
(事件的最後一環)onTouchEvent()
-
優先于OnTouchListener
對事件進行消費onTouchEvent()
技巧
對于底層的View來說,可以使用
getParent().requestDisallowInterceptTouchEvent(true)
來阻止父View攔截Touch事件.
實踐過程中,常用與解決嵌套滑動事件沖突的問題:如scrollView+listview方式,此時可重寫onTouchEvent判斷滑動位置.
當子View需要滑動時,在子view中使用
requestDisallowInterceptTouchEvent(true);
阻止父View攔截消費事件
當子view滑動到邊界才
requestDisallowInterceptTouchEvent(false);