触摸事件 ACTION_UP/ACTION_MOVE 的分发

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 移动

总的来说触摸事件的 传递流程 是:

  1. dispatchTouchEvent() -> onInterceptTouchEvent() -> onTouchEvent();
  2. dispatchTouchEvent 传递顺序: Activity -> ViewGroup -> View;
  3. onTouchEvent 传递顺序 View -> ViewGroup -> Activity;

如果哪一个步骤的方法返回了 true, 则传递不会继续传给下一个流程


分析

假设 Activity 中有一个 ViewGroup, ViewGroup 中有一个 View

测试下面几种情况

默认操作, 不消费点击事件

现象

结论

走完 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

现象

结论

走完 ACTIONDOWN 的完整流程后, 发现事件被 ViewGroup 消费事件, 则 ACTIONUP/ACTION_MOVE 不会再往 View 转发;

在 ViewGroup 中消费事件, 同时打断事件: onTouchEvent/onInterceptTouchEvent 返回 true

现象

结论

被打断后, 不在向 View 转发; 走完 ACTIONDOWN 的完整流程后, 发现事件被 ViewGroup 消费事件, 则 ACTIONUP/ACTION_MOVE 不会再往 View 转发;

在 View 中消费事件: dispatchTouchEvent 返回 true

现象

结论

消费后, 不再传递;


总结:
  • ViewGroup 的 onInterceptTouchEvent 只会在 ACTION_DOWN 执行一次
  • 事件在 ViewGroup 消费, 后续事件也不会再往该 ViewGroup 的下级转发
  • 事件在ACTIONDOWN的传递过程中被消费了, ACTIONUP/ACTION_MOVE 才会被传出 Activity
0 Comments
Leave a Reply