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

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

onInterceptTouchEvent, dispatchTouchEvent和onTouchEvent如何在视图(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);
}

其他回答

Activity和View都有dispatchTouchEvent()和onTouchEvent方法。ViewGroup也有这个方法,但是有另一个叫做onInterceptTouchEvent的方法。这些方法的返回类型是布尔型,您可以通过返回值控制调度路由。

Android中的事件调度从Activity->ViewGroup->View开始。

主要区别:

•Activity. dispatchtouchevent (MotionEvent) -这允许您的Activity 来拦截所有的触摸事件,然后再将它们分派到 窗口。 •ViewGroup.onInterceptTouchEvent(MotionEvent) -这允许一个 ViewGroup来监视事件,因为它们被分派到子视图。

public boolean dispatchTouchEvent(MotionEvent ev){
    boolean consume =false;
    if(onInterceptTouchEvent(ev){
        consume = onTouchEvent(ev);
    }else{
        consume = child.dispatchTouchEvent(ev);
    }
}

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;
  }

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

因为这是谷歌的第一个结果。我想在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);
}