Android中onInterceptTouchEvent和dispatchTouchEvent的区别是什么?

根据android开发者指南,这两种方法都可以用来拦截触摸事件(MotionEvent),但有什么区别呢?

onInterceptTouchEvent, dispatchTouchEvent和onTouchEvent如何在视图(ViewGroup)的层次结构中一起交互?


当前回答

补充回答

以下是对其他答案的视觉补充。我的完整答案在这里。

ViewGroup的dispatchTouchEvent()方法使用onInterceptTouchEvent()来选择是否应该立即处理触摸事件(使用onTouchEvent())或继续通知其子方法的dispatchTouchEvent()。

其他回答

揭开这一神秘面纱的最佳地点是源代码。医生们对这一点解释得很不充分。

dispatchTouchEvent实际上定义在Activity, View和ViewGroup上。可以把它看作一个控制器,它决定如何路由触摸事件。

例如,最简单的情况是视图。dispatchTouchEvent将触摸事件路由到OnTouchListener。onTouch(如果它是定义的)或者扩展方法onTouchEvent。

ViewGroup。dispatchTouchEvent的事情要复杂得多。它需要找出它的哪个子视图应该获得事件(通过调用child. dispatchtouchevent)。这基本上是一个命中测试算法,其中你计算出哪个子视图的边界矩形包含触点坐标。

But before it can dispatch the event to the appropriate child view, the parent can spy and/or intercept the event all together. This is what onInterceptTouchEvent is there for. So it calls this method first before doing the hit testing and if the event was hijacked (by returning true from onInterceptTouchEvent) it sends a ACTION_CANCEL to the child views so they can abandon their touch event processing (from previous touch events) and from then onwards all touch events at the parent level are dispatched to onTouchListener.onTouch (if defined) or onTouchEvent(). Also in that case, onInterceptTouchEvent is never called again.

你甚至想要覆盖[活动|ViewGroup|View].dispatchTouchEvent?除非您正在进行一些自定义路由,否则您可能不应该这样做。

主要的扩展方法是ViewGroup。onInterceptTouchEvent(如果你想监视和/或拦截父级的触摸事件)和View. ontouchlistener /View。onTouchEvent用于主事件处理。

总的来说,在我看来,它的设计过于复杂,但android api更倾向于灵活性而不是简单性。

答:小

onInterceptTouchEvent出现在setOnTouchListener之前。

ViewGroup子类中的以下代码将阻止它的父容器接收触摸事件:

  @Override
  public boolean dispatchTouchEvent(MotionEvent ev) {
    // Normal event dispatch to this container's children, ignore the return value
    super.dispatchTouchEvent(ev);

    // Always consume the event so it is not dispatched further up the chain
    return true;
  }

我使用自定义覆盖来防止背景视图响应触摸事件。

ViewGroup的onInterceptTouchEvent()总是ACTION_DOWN事件的入口点,这是第一个发生的事件。

如果你想让ViewGroup处理这个手势,从onInterceptTouchEvent()返回true。 在返回true时,ViewGroup的onTouchEvent()将接收到下一次ACTION_UP或ACTION_CANCEL之前的所有后续事件,在大多数情况下,ACTION_DOWN和ACTION_UP或ACTION_CANCEL之间的触摸事件为ACTION_MOVE,通常会被识别为滚动/抛动手势。

如果你从onInterceptTouchEvent()返回false,目标视图的onTouchEvent()将被调用。它将被重复用于后续的消息,直到你从onInterceptTouchEvent()返回true。

来源: http://neevek.net/posts/2013/10/13/implementing-onInterceptTouchEvent-and-onTouchEvent-for-ViewGroup.html

你可以在这个视频https://www.youtube.com/watch?v=SYoN-OvdZ3M&list=PLonJJ3BVjZW6CtAMbJz1XD8ELUs1KXaTD&index=19和接下来的三个视频中找到答案。所有的触摸事件都解释得很好,它非常清楚,充满了例子。