onInterceptTouchEvent永远不会收到action_move动作

9

我有一个自定义的ViewGroup,并重写了onInterceptTouchEvent()方法。它能接收到ACTION_DOWN事件,但无法接收到ACTION_MOVE事件。据我的理解,除非返回“true”,否则它应该能接收所有的MotionEvent事件。

这个ViewGroup包含两个视图,即ImageView和GridLayout。

我的拦截代码是:

  @Override
  public boolean onInterceptTouchEvent(MotionEvent ev)
  {
    final int action = ev.getAction();
    switch (action & MotionEvent.ACTION_MASK)
    {
      case MotionEvent.ACTION_DOWN:
        logD ("DDV Intercept DOWN");
        break;
      case MotionEvent.ACTION_POINTER_DOWN:
        logD ("DDV Intercept P DOWN"); // logD: shell around Log.d()
        break;
      case MotionEvent.ACTION_MOVE:
        logD ("DDV Intercept MOVE");
        break;
      case MotionEvent.ACTION_UP:
        logD ("DDV Intercept UP");
        break;
      case MotionEvent.ACTION_POINTER_UP:
        logD ("DDV Intercept P UP " + ev.getActionIndex());
        break;
      case MotionEvent.ACTION_CANCEL: 
        logD ("DDV Intercept CANCEL");
        break;
      default:
        logD ("DDV Intercept " + (action & MotionEvent.ACTION_MASK));
    }        
    return false;
  }

我还有一个onTouch的代码,除了ACTION_MOVE之外都返回false;然而,它只在ACTION_DOWN被调用时被调用,因此它只返回false。

1个回答

27
这比较复杂。首先,您需要覆盖 onTouchEvent() 方法,并在其中处理 ACTION_DOWNMOVE 事件。然后会发生以下情况。
  1. ACTION_DOWN 事件首先被派发到 onInterceptTouchEvent()。您应该从那里返回 false
  2. 现在有两种情况:
    • 如果视图树中 ACTION_DONW 事件的位置下面没有可触摸的视图,则 ACTION_DOWN 事件和所有后续事件都将被派发到 onTouchEvent()。您必须从那里返回 true。只有这样,您才能接收到发送到 onTouchEvent() 方法的后续事件。无论您返回 true 还是 falseonInterceptTouchEvent() 都不会再接收到任何后续事件。
    • 如果有一个可触摸的视图,则所有事件(包括 ACTION_MOVE 事件)都会被派发到 onInterceptTouchEvent()。您需要在检测到手势后从这里返回 true。一旦您从此处返回 true,可触摸视图将接收 ACTION_CANCEL 事件,并且所有后续事件将被派发到 onTouchEvent() 方法。
希望对您有所帮助。

1
我更新了我的回答。如果没有可触摸的子元素,DOWN 事件将被传递到 onTouchEvent(),你必须从那里返回 true 才能获得后续事件。如果你返回 false,则不会将任何事件传递到 onInterceptTouchEvent() 或 onTouchEvent()。 - sergej shafarenka
1
啊,这与我的经验相符。但是它与文档不同。我希望还有其他遗漏的东西。谢谢您的验证。 - Peri Hartman
1
没错。关于 onInterceptTouchEvent() 的文档非常误导。 - sergej shafarenka
我也曾认为这很荒谬,但是一旦我理解了这个想法,一切都变得合乎逻辑。重点是,如果没有视图对DOWN事件感兴趣,则Android不会传递更多事件。如果有可触摸的子视图,则所有事件都将传递给该子视图。这就是onIntercept...发挥作用的地方。如果没有可触摸的子视图,则您的视图必须通过从onTouchEvent()返回true来表达接收此事件的兴趣。在这种情况下,没有理由调用onIntercept...,因为所有事件已经传递到您的onTouchEvent中,没有什么可以拦截的 ;) - sergej shafarenka
嗯,那有点道理。但不幸的是,他们没有考虑到子视图仅用于显示目的且不需要处理任何触摸事件的情况。在这种情况下,除非它立即返回true,否则父级将无法接收onIntercept...或onTouch。但是立即返回true意味着它不是通用容器-它必须知道子项是否处理触摸事件。诚然,没有处理触摸事件的子项可能是一个相当罕见的情况,并且我认为很容易被忽视或认为不重要。 - Peri Hartman
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接