onInterceptTouchEvent,onTouchEvent只能看到ACTION_DOWN

时间:2012-09-25 23:35:06

标签: android scrollview android-linearlayout ontouchevent motionevent

我有一个顶级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”;我还没弄清楚它的含义以及它的相关性。

4 个答案:

答案 0 :(得分:5)

由于user123321 here

的回答
  

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

答案 1 :(得分:3)

您只需拨打电话

即可
requestDisallowInterceptTouchEvent(true);
父视图上的

,像这样 -

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

            return false; 

         }

答案 2 :(得分:1)

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

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

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

答案 3 :(得分:0)

当拦截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。

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

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