Touch 事件的分发和消费机制

首先应该明确事件的分发和拦截是从父view向下传递的,而事件的响应是从下向上传递的```

Android 中与 Touch 事件相关的方法包括:

  • dispatchTouchEvent(MotionEvent ev)
  • onInterceptTouchEvent(MotionEventev)
  • onTouchEvent(MotionEvent ev)

能够响应这些方法的控件包括:ViewGroup、View、Activity。方法与控件的对应关系如下表所示:

Touch 事件相关方法 方法功能 ViewGroup View Activity
public boolean dispatchTouchEvent(MotionEvent ev) 事件分发 Yes Yes Yes
public boolean onInterceptTouchEvent(MotionEvent ev) 事件拦截 Yes Yes No
public boolean onTouchEvent(MotionEvent ev) 事件响应 Yes Yes Yes

从这张表中我们可以看到 ViewGroup 和 View 对与 Touch 事件相关的三个方法均能响应,而Activity 对 onInterceptTouchEvent(MotionEvent ev) 也就是事件拦截不进行响应。另外需要注意的是 View 对dispatchTouchEvent(MotionEvent ev)onInterceptTouchEvent(MotionEventev) 的响应的前提是可以向该View 中添加子 View,如果当前的 View 已经是一个最小的单元 View(比如 TextView ),那么就无法向这个最小 View 中添加子 View,也就无法向子 View 进行事件的分发和拦截,所以它没dispatchTouchEvent(MotionEvent ev)onInterceptTouchEvent(MotionEventev),只有onTouchEvent(MotionEvent ev)

Touch 事件分析

事件分发:public boolean dispatchTouchEvent(MotionEvent ev)

Touch 事件发生时 Activity 的 dispatchTouchEvent(MotionEvent ev)方法会以隧道方式(从根元素依次往下传递直到最内层子元素或在中间某一元素中由于某一条件停止传递)将事件传递给最外层 View 的dispatchTouchEvent(MotionEvent ev) 方法,并由该 View 的dispatchTouchEvent(MotionEvent ev)方法对事件进行分发。

dispatchTouchEvent 的事件分发逻辑如下:

  • 如果 return true,事件会分发给当前 View 并由
    dispatchTouchEvent方法进行消费,同时事件会停止向下传递;不会触发任何 onTouch,如果 return false,事件分发分为两种情况:
  • 如果当前 View 获取的事件直接来自 Activity,则会将事件返回给Activity 的 onTouchEvent进行消费;
  • 如果当前View 获取的事件来自外层父控件,则会将事件返回给父View 的 onTouchEvent 进行消费。
  • 如果返回系统默认的 super.dispatchTouchEvent(ev),事件会自动的分发给当前View 的onInterceptTouchEvent方法。

事件拦截 public boolean onInterceptTouchEvent(MotionEvent ev)

在外层 View 的 dispatchTouchEvent(MotionEvent ev) 方法返回系统默认的super.dispatchTouchEvent(ev) 情况下,事件会自动的分发给当前 View 的 onInterceptTouchEvent方法。

onInterceptTouchEvent 的事件拦截逻辑如下:

  • 如果onInterceptTouchEvent返回 true,则表示将事件进行拦截,并将拦截到的事件交由当前 View 的onTouchEvent 进行处理;
  • 如果onInterceptTouchEvent 返回 false,则表示将事件放行,当前 View 上的事件会被传递到子 View 上,再由子 View 的dispatchTouchEvent来开始这个事件的分发;
  • 如果onInterceptTouchEvent 返回 super.onInterceptTouchEvent(ev),事件默认会被拦截,并将拦截到的事件交由当前 View 的onTouchEvent进行处理。

事件响应:public boolean onTouchEvent(MotionEvent ev)

dispatchTouchEvent返回 super.dispatchTouchEvent(ev)并且onInterceptTouchEvent返回 true 或返回super.onInterceptTouchEvent(ev)的情况下onTouchEvent会被调用

onTouchEvent 的事件响应逻辑如下:

  • 如果事件传递到当前View 的onTouchEvent 方法,而该方法返回了false,那么这个事件会从当前View 向上传递,并且都是由上层View 的onTouchEvent 来接收,如果传递到上面的onTouchEvent 也返回false,这个事件就会“消失”,而且接收不到下一次事件。如果返回了true 则会接收并消费该事件。
  • 如果返回super.onTouchEvent(ev) 默认处理事件的逻辑和返回false 时相同。onTouchListeneronTouch方法优先级比onTouchEvent高,会先触发。假如onTouch方法返回 false 会接着触发onTouchEvent,反之onTouchEvent方法不会被调用。当 onTouch 返回 false 时,onTouch的 down \ move \ up 等事件不会执行,返回true时,onTouch事件的 Move 和 up 事件继续分发到 OnTouch

你可能感兴趣的:(Touch 事件的分发和消费机制)