MotionEvent 的 ACTIONDOWN 是按照传递流程执行的, 但是 ACTIONUP/ACTION_MOVE 的传递过程会 受到事件是否被消费的影响 (被消费指的是方法返回 true )
基础知识
触摸事件的分发主要涉及以下三个方法
- boolean dispatchTouchEvent(MotionEvent event)
- boolean onTouchEvent(MotionEvent event)
- boolean onInterceptTouchEvent(MotionEvent event) // ViewGroup 独有
MotionEvent 有三种动作 (actoin)
- ACTION_DOWN 按下
- ACTION_UP 抬起
- ACTION_MOVE 移动
总的来说触摸事件的 传递流程 是:
- dispatchTouchEvent() -> onInterceptTouchEvent() -> onTouchEvent();
- dispatchTouchEvent 传递顺序: Activity -> ViewGroup -> View;
- onTouchEvent 传递顺序 View -> ViewGroup -> Activity;
如果哪一个步骤的方法返回了 true, 则传递不会继续传给下一个流程
分析
假设 Activity 中有一个 ViewGroup, ViewGroup 中有一个 View
测试下面几种情况
默认操作, 不消费点击事件
1 2 3 4 5 6 |
Activity: dispatchTouchEvent(super)/onTouchEvent(super) ViewGroup: dispatchTouchEvent(super)/onInterceptTouchEvent(super)/onTouchEvent(super) View: dispatchTouchEvent(super)/onTouchEvent(super) |
现象
1 2 3 4 5 6 7 8 9 10 11 12 |
ACTION_DOWN: Activity dispatchTouchEvent ViewGroup dispatchTouchEvent ViewGroup onInterceptTouchEvent // onInterceptTouchEvent 在分发给 View 之前 View dispatchTouchEvent TextView onTouchEvent ViewGroup onTouchEvent Activity onTouchEvent ACTION_UP/ACTION_MOVE: Activity dispatchTouchEvent Activity onTouchEvent |
结论
走完 ACTIONDOWN 的完整流程后, 发现没有控件会消费触摸事件, 则 ACTIONUP/ACTION_MOVE 只在 Activity 中处理;
在 ViewGroup 中拦截事件,onInterceptTouchEvent 返回 true
Activity:
dispatchTouchEvent(super)/onTouchEvent(super)
ViewGroup:
dispatchTouchEvent(super)/onInterceptTouchEvent(true)/onTouchEvent(super)
View:
dispatchTouchEvent(super)/onTouchEvent(super)
现象
ACTION_DOWN:
Activity dispatchTouchEvent
ViewGroup dispatchTouchEvent
ViewGroup onInterceptTouchEvent
ViewGroup onTouchEvent
Activity onTouchEvent
ACTIONUP/ACTIONMOVE:
Activity dispatchTouchEvent
Activity onTouchEvent
结论
被打断后, 不再向 View 转发; 打断不是消费事件, 走完 ACTIONDOWN 的完整流程后, 发现没有控件消费触摸事件, 则 ACTIONUP/ACTION_MOVE 只在 Activity 中处理;
在 ViewGroup 中消费事件: onTouchEvent 返回 true
1 2 3 4 5 6 |
Activity: dispatchTouchEvent(super)/onTouchEvent(super) ViewGroup: dispatchTouchEvent(super)/onInterceptTouchEvent(super)/onTouchEvent(true) View: dispatchTouchEvent(super)/onTouchEvent(super) |
现象
1 2 3 4 5 6 7 8 9 10 11 12 |
ACTION_DOWN:// 传递给 View 的 onTouchEvent Activity dispatchTouchEvent ViewGroup dispatchTouchEvent ViewGroup onInterceptTouchEvent TextView dispatchTouchEvent TextView onTouchEvent ViewGroup onTouchEvent ACTION_UP/ACTION_MOVE:// 后续事件不再传递给 View Activity dispatchTouchEvent ViewGroup dispatchTouchEvent ViewGroup onTouchEvent |
结论
走完 ACTIONDOWN 的完整流程后, 发现事件被 ViewGroup 消费事件, 则 ACTIONUP/ACTION_MOVE 不会再往 View 转发;
在 ViewGroup 中消费事件, 同时打断事件: onTouchEvent/onInterceptTouchEvent 返回 true
1 2 3 4 5 6 |
Activity: dispatchTouchEvent(super)/onTouchEvent(super) ViewGroup: dispatchTouchEvent(super)/onInterceptTouchEvent(super)/onTouchEvent(true) View: dispatchTouchEvent(super)/onTouchEvent(super) |
现象
1 2 3 4 5 6 7 8 9 10 |
ACTION_DOWN:// 没有传给 View Activity dispatchTouchEvent ViewGroup dispatchTouchEvent ViewGroup onInterceptTouchEvent ViewGroup onTouchEven ACTION_UP/ACTION_MOVE:// 不再传递给 View Activity dispatchTouchEvent ViewGroup dispatchTouchEvent ViewGroup onTouchEvent |
结论
被打断后, 不在向 View 转发; 走完 ACTIONDOWN 的完整流程后, 发现事件被 ViewGroup 消费事件, 则 ACTIONUP/ACTION_MOVE 不会再往 View 转发;
在 View 中消费事件: dispatchTouchEvent 返回 true
1 2 3 4 5 6 |
Activity: dispatchTouchEvent(super)/onTouchEvent(super) ViewGroup: dispatchTouchEvent(super)/onInterceptTouchEvent(super)/onTouchEvent(super) View: dispatchTouchEvent(true)/onTouchEvent(super) |
现象
1 2 3 4 5 6 7 8 9 10 11 |
ACTION_DOWN: Activity dispatchTouchEvent ViewGroup dispatchTouchEvent ViewGroup onInterceptTouchEvent View dispatchTouchEvent ACTION_UP/ACTION_MOVE: Activity dispatchTouchEvent ViewGroup dispatchTouchEvent ViewGroup onInterceptTouchEvent View dispatchTouchEvent |
结论
消费后, 不再传递;
总结:
- ViewGroup 的 onInterceptTouchEvent 只会在 ACTION_DOWN 执行一次
- 事件在 ViewGroup 消费, 后续事件也不会再往该 ViewGroup 的下级转发
- 事件在ACTIONDOWN的传递过程中被消费了, ACTIONUP/ACTION_MOVE 才会被传出 Activity
0 Comments