【问题标题】:onInterceptTouchEvent, onTouchEvent only see ACTION_DOWNonInterceptTouchEvent,onTouchEvent 只看到 ACTION_DOWN
【发布时间】:2012-09-25 23:35:06
【问题描述】:

我有一个顶级 ViewGroup,我称之为 SliderView,我想在其中检测滑动。这主要是有效的,但一个奇怪的失败仍然存在。

SliderView 的本质是重写 onInterceptTouchEvent,一旦用户真正滑动,返回“true”以防止其他视图看到 MotionEvent。这是一段代码:

public class SliderView extends ViewGroup
{
  enum MoveState { MS_NONE, MS_HSCROLL, MS_VSCROLL };
  private MoveState moveState = MoveState.MS_NONE;

  ... other code ...

  public boolean onInterceptTouchEvent(MotionEvent e)
  {
    final int action = e.getAction();
    switch (action & MotionEvent.ACTION_MASK)
    {
      case MotionEvent.ACTION_DOWN:
        moveState = MoveState.MS_NONE;
        break;

      case MotionEvent.ACTION_MOVE:
        if (moveState == MoveState.MS_NONE)
        {
          if (motion is horizontal)
          {
            moveState = MoveState.MS_VSCROLL;
            return true;
          }
          else
            moveState = MoveState.MS_VSCROLL; // let child window handl MotionEvent
        }
        else if (moveState == MoveState.MS_HSCROLL)
          return true; // don't let children see motion event.
    }
    return super.onInterceptTouchEvent (e);
  }

  ... other code ...
}

据我了解,我的 SliderView(它是最外层的视图)应该始终接收 onInterceptTouchEvent。在我的一项测试中,顶级子级是 a 但是,在以下情况下,这似乎不是。

当顶级子级是 ScrollView 时,onInterceptTouchEvent 会获取 ACTION_MOVE,我的代码会执行我想要的操作。在另一种情况下,顶级子级是 LinearLayout,它有时会失败:它总是获得 ACTION_DOWN 但只有当用户触摸 LinearLayout 内的小部件时才会获得 ACTION_MOVE;如果触摸空白区域,则只有 ACTION_DOWN 通过。

我会注意到它的行为就好像失败案例触摸发生在 SliderView 之外。但是,如果是这样,我为什么会收到 ACTION_DOWN 事件?

第二点:查看 ScrollView 的源代码,我看到它正在检查“inChild”;我还没有弄清楚它的用途以及它的相关性。

【问题讨论】:

  • 你解决过这个问题吗?
  • 不,但是在阅读更多文档时,我了解到有一种叫做 ViewPager 的东西,它包含了水平滑动。我还没有尝试过,因为我现在正在充实其他东西。我不知道您要做什么,但如果您尝试使用 ViewPager,请告诉我结果。

标签: android scrollview android-linearlayout touch-event motionevent


【解决方案1】:

由于user123321here的回答

onInterceptTouchEvent 仅在父视图具有从 onTouchEvent 返回“true”的子视图时才会被调用。一旦孩子返回 true,父母现在就有机会拦截该事件

【讨论】:

    【解决方案2】:

    你只需要打电话

    requestDisallowInterceptTouchEvent(true);
    

    在父视图上,像这样 -

            @Override
            public boolean onTouch(View view, MotionEvent motionEvent) {
                view.getParent().requestDisallowInterceptTouchEvent(true);
                switch(motionEvent.getActio){
                }
    
                return false; 
    
             }
    

    【讨论】:

    • 这可能是一个正确的答案,但由于这个问题已经很老了——而且我的代码早已演变成别的东西——我无法验证。
    • 对不起,我不明白你的问题。
    【解决方案3】:

    来自 Android 开发者的参考资料 (http://developer.android.com/reference/android/view/ViewGroup.html#onInterceptTouchEvent(android.view.MotionEvent)):

    "2. .... 另外,通过从 onTouchEvent() 返回 true,您将不会在 onInterceptTouchEvent() 中收到任何后续事件,并且所有触摸处理都必须像往常一样在 onTouchEvent() 中发生。"

    也许是因为你的 onTouchEvent 总是返回 true..?

    【讨论】:

    • 实际上,只有两种情况它返回“true”。其他情况返回 super.onInterceptTouchEvent()。
    【解决方案4】:

    在拦截 onTouchEvent 时,需要做两件事来正确拦截触摸(其他都是默认设置)。

    1. 在 onInterceptTouchEvent() 中返回 false

      @Override
      public boolean onInterceptTouchEvent(MotionEvent me) {
          return false;
      }
      
    2. 在 onTouchEvent() 中返回 true

      @Override
      public boolean onTouchEvent(MotionEvent me) {
      
          switch (me.getAction()) {
          case MotionEvent.ACTION_DOWN:
              log("MotionEvent.ACTION_DONE");
              break;
          case MotionEvent.ACTION_MOVE:
              log("MotionEvent.ACTION_MOVE");
              break;
          case MotionEvent.ACTION_CANCEL:
              log("MotionEvent.ACTION_CANCEL");
              userActionDown = false;
              break;
          case MotionEvent.ACTION_UP:
              log("MotionEvent.ACTION_UP");
              break;
          }
      
          return true;
      }
      
    3. 然后,对于您的情况(和其他情况)。如上所示,在 onTouchEvent() 中进行所有计算。 onInterceptTouchEvent() 只会为 ACTION_DOWN 调用一次。但是,onTouchEvent 也会得到 ACTION_DOWN 事件,你需要在那里返回 true,而不是 super。

    有关 onInterceptTouchEvent() 的更多信息:http://developer.android.com/reference/android/view/ViewGroup.html#onInterceptTouchEvent(android.view.MotionEvent)

    ps - 当你在这里提问时,你还应该写下你想要做什么的描述。你很可能会找到更好的做事方式。对于您的导航案例,您正在寻找的真正答案是ViewPager。它工作得很好并且很容易实现。您还应该查看 Android 必须为开发人员提供的其他一些简单的导航模式:link

    【讨论】:

    • 我早在 2012 年 11 月就发现了 ViewPager,并在上面进行了说明。
    • 是的,这就是我评论它的原因。你说:I haven't tried it yet as I'm fleshing out other stuff right now. I don't know what you're seeking to do, but if you try ViewPager please let me know the outcome. 所以,我让你知道结果,因为我使用了 ViewPager。 ;) 还有问题吗?
    • 是的,我试过了,效果很好。请看stackoverflow.com/questions/13664155/…
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-02-08
    • 2012-01-12
    • 1970-01-01
    • 2011-09-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多