我有一个顶级ViewGroup,我称它为SliderView,我想在其中检测滑动。这通常可以正常工作,但是一个奇怪的失败仍然存在。

SliderView的本质是重写onInterceptTouchEvent,并且在用户实际滑动后,返回“true”以防止其他 View 占用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(最外面的 View )应始终接收onInterceptTouchEvent。在我的一项测试中,顶级子级是A。但是,在以下情况下,情况似乎并非如此。

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

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

第二点:查看ScrollView的源代码,我看到它检查了“inChild”;我还没有弄清楚这是做什么用的,以及它可能如何与之相关。

最佳答案

由于user123321的回答here

10-08 12:30