Android中onInterceptTouchEvent和dispatchTouchEvent的区别是什么?
根据android开发者指南,这两种方法都可以用来拦截触摸事件(MotionEvent),但有什么区别呢?
onInterceptTouchEvent, dispatchTouchEvent和onTouchEvent如何在视图(ViewGroup)的层次结构中一起交互?
Android中onInterceptTouchEvent和dispatchTouchEvent的区别是什么?
根据android开发者指南,这两种方法都可以用来拦截触摸事件(MotionEvent),但有什么区别呢?
onInterceptTouchEvent, dispatchTouchEvent和onTouchEvent如何在视图(ViewGroup)的层次结构中一起交互?
当前回答
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
其他回答
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的dispatchTouchEvent()方法使用onInterceptTouchEvent()来选择是否应该立即处理触摸事件(使用onTouchEvent())或继续通知其子方法的dispatchTouchEvent()。
主要区别:
•Activity. dispatchtouchevent (MotionEvent) -这允许您的Activity 来拦截所有的触摸事件,然后再将它们分派到 窗口。 •ViewGroup.onInterceptTouchEvent(MotionEvent) -这允许一个 ViewGroup来监视事件,因为它们被分派到子视图。
因为这是谷歌的第一个结果。我想在Youtube上分享Dave Smith的演讲:精通Android触摸系统,幻灯片可以在这里找到。让我对Android Touch System有了一个很深刻的了解:
Activity如何处理触摸:
Activity.dispatchTouchEvent () 总是第一个被叫到 发送事件到附加到窗口的根视图 onTouchEvent () 如果没有视图使用该事件则调用 总是最后一个被叫
视图如何处理触摸:
View.dispatchTouchEvent () 如果存在,首先向监听器发送事件 View.OnTouchListener.onTouch () 如果未被消费,则处理触摸本身 View.onTouchEvent ()
ViewGroup如何处理触摸:
ViewGroup.dispatchTouchEvent() onInterceptTouchEvent() Check if it should supersede children Passes ACTION_CANCEL to active child If it returns true once, the ViewGroup consumes all subsequent events For each child view (in reverse order they were added) If touch is relevant (inside view), child.dispatchTouchEvent() If it is not handled by a previous, dispatch to next view If no children handles the event, the listener gets a chance OnTouchListener.onTouch() If there is no listener, or its not handled onTouchEvent() Intercepted events jump over the child step
他还在github.com/devunwired/上提供了定制触摸的示例代码。
Answer: Basically the dispatchTouchEvent() is called on every View layer to determine if a View is interested in an ongoing gesture. In a ViewGroup the ViewGroup has the ability to steal the touch events in his dispatchTouchEvent()-method, before it would call dispatchTouchEvent() on the children. The ViewGroup would only stop the dispatching if the ViewGroup onInterceptTouchEvent()-method returns true. The difference is that dispatchTouchEvent()is dispatching MotionEvents and onInterceptTouchEvent tells if it should intercept (not dispatching the MotionEvent to children) or not (dispatching to children).
你可以想象ViewGroup的代码或多或少是这样做的(非常简化):
public boolean dispatchTouchEvent(MotionEvent ev) {
if(!onInterceptTouchEvent()){
for(View child : children){
if(child.dispatchTouchEvent(ev))
return true;
}
}
return super.dispatchTouchEvent(ev);
}
揭开这一神秘面纱的最佳地点是源代码。医生们对这一点解释得很不充分。
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更倾向于灵活性而不是简单性。