5

我在 ViewFlipper 中有一个 ListView,当用户在屏幕上滑动时我正在翻转它。单击 ListView 将打开浏览器。有时,当我滑动时,它会被检测为对 ListView 的触摸,并会打开浏览器。这可能很烦人。我怎样才能防止这种情况发生?

class MyGestureDetector extends SimpleOnGestureListener {
        @Override
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
            try {
                if (Math.abs(e1.getY() - e2.getY()) > SWIPE_MAX_OFF_PATH)
                    return false;
                // right to left swipe
                if (e1.getX() - e2.getX() > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
                    viewFlipper.setInAnimation(slideLeftIn);
                    viewFlipper.setOutAnimation(slideLeftOut);
                    viewFlipper.showNext();
                } else if (e2.getX() - e1.getX() > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
                    viewFlipper.setInAnimation(slideRightIn);
                    viewFlipper.setOutAnimation(slideRightOut);
                    viewFlipper.showPrevious();
                }

                if (viewFlipper.getDisplayedChild() == 0) {
                    // TODO: light up left
                    flipperPosition = 0;
                } else if (viewFlipper.getDisplayedChild() == 1) {
                    // TODO: light up middle
                    flipperPosition = 1;
                } else if (viewFlipper.getDisplayedChild() == 2) {
                    // TODO: light up right
                    flipperPosition = 2;
                }
            } catch (Exception e) {
                System.out.println(e);
            }
            return false;
        }
    }

protected MotionEvent downStart = null;  

        public boolean onInterceptTouchEvent(MotionEvent event) {  

            switch(event.getAction()) {  
            case MotionEvent.ACTION_DOWN:  
                // keep track of the starting down-event  
                downStart = MotionEvent.obtain(event);  
                break;  
            case MotionEvent.ACTION_MOVE:  
                // if moved horizontally more than slop*2, capture the event for ourselves  
                float deltaX = event.getX() - downStart.getX();  
                if(Math.abs(deltaX) > ViewConfiguration.getTouchSlop() * 2)  
                    return true;  
                break;  
            }  

            // otherwise let the event slip through to children  
            return false;  
        }  
4

2 回答 2

14

这通常是通过父视图的onInterceptTouchEvent方法来完成的。onInterceptTouchEvent有机会在视图的孩子之前看到任何触摸事件。如果onInterceptTouchEvent返回true之前处理触摸事件的子视图,则会收到一个ACTION_CANCEL,并且从该点开始的事件将被发送到父级的onTouchEvent方法以进行通常的处理。它还可以返回false并简单地监视事件,因为它们沿着视图层次结构向下移动到它们通常的目标。

您基本上想onInterceptTouchEvent在您检测到 fling 的父视图中执行此操作:

  • 在 上ACTION_DOWN,记录触摸的位置。返回false
  • 在 上ACTION_MOVE,检查初始着陆位置和当前位置之间的增量。如果它超过阈值,(框架使用ViewConfiguration#getScaledTouchSlop()或其他适当的值来自ViewConfiguration类似的东西,)返回true
  • 基于onTouchEvent.

拦截后,ListView将取消其触摸处理,并且您不会在列表项上收到不需要的点击事件。ListView一旦用户开始垂直滚动列表,也设置为禁止其父级拦截事件,这意味着如果用户草率地垂直滚动列表,您将不会错误地水平滚动。

这就是像普通的 Android 启动器或新闻和天气这样的东西对滚动/可点击内容进行并排分页的方式。

于 2010-09-30T21:23:33.227 回答
1

您是否尝试过将 SimpleOnGestureListener.onSingleTapConfirmed(MotionEvent) 用于触摸事件(“点击”)?这只会在检测器确信用户的第一次点击确实是点击而不是双击(或希望是一扔)后调用。

class MyGestureDetector extends SimpleOnGestureListener {
    @Override
    public boolean onSingleTapConfirmed(MotionEvent event) {
        // Code...
    }
}
于 2010-09-30T19:51:11.580 回答