如何在一扔和触摸区分?在一

2023-09-04 10:43:28 作者:久别无恙°

我有一个ViewFlipper当用户在屏幕上挥笔而我翻转里面一个ListView。点击一个ListView将打开浏览器。有时,当我刷卡,它就会被检测为ListView的触摸,将打开浏览器。这可以是恼人。我怎样才能prevent这种情况的发生?

 类MyGestureDetector扩展SimpleOnGestureListener {
        @覆盖
        公共布尔onFling(MotionEvent E1,E2 MotionEvent,浮velocityX,浮velocityY){
            尝试 {
                如果(Math.abs(e1.getY() -  e2.getY())> SWIPE_MAX_OFF_PATH)
                    返回false;
                //从右向左轻扫
                如果(e1.getX() -  e2.getX()> SWIPE_MIN_DISTANCE&安培;&安培; Math.abs(velocityX)> SWIPE_THRESHOLD_VELOCITY){
                    viewFlipper.setInAnimation(slideLeftIn);
                    viewFlipper.setOutAnimation(slideLeftOut);
                    viewFlipper.showNext();
                }否则,如果(e2.getX() -  e1.getX()> SWIPE_MIN_DISTANCE和放大器;&安培; Math.abs(velocityX)> SWIPE_THRESHOLD_VELOCITY){
                    viewFlipper.setInAnimation(slideRightIn);
                    viewFlipper.setOutAnimation(slideRightOut);
                    viewFlipper.show previous();
                }

                如果(viewFlipper.getDisplayedChild()== 0){
                    // TODO:点亮左
                    flipperPosition = 0;
                }否则如果(viewFlipper.getDisplayedChild()== 1){
                    // TODO:点亮中间
                    flipperPosition = 1;
                }否则如果(viewFlipper.getDisplayedChild()== 2){
                    // TODO:点亮权
                    flipperPosition = 2;
                }
            }赶上(例外五){
                的System.out.println(E);
            }
            返回false;
        }
    }

保护MotionEvent downStart = NULL;

        公共布尔onInterceptTouchEvent(MotionEvent事件){

            开关(event.getAction()){
            案例MotionEvent.ACTION_DOWN:
                //跟踪开始向下事件
                downStart = MotionEvent.obtain(事件);
                打破;
            案例MotionEvent.ACTION_MOVE:
                //如果水平移动比坡* 2个,捕获事件占为己有
                浮DELTAX = event.getX() -  downStart.getX();
                如果(Math.abs(DELTAX)> ViewConfiguration.getTouchSlop()* 2)
                    返回true;
                打破;
            }

            //否则让通过事件溜儿
            返回false;
        }
 

解决方案

的方式,这是通常做的是通过父视图的onInterceptTouchEvent方法。 onInterceptTouchEvent 有机会看到任何触摸事件前视图的孩子做。如果 onInterceptTouchEvent 返回这是子视图previously处理触摸事件接收 ACTION_CANCEL ,并从该点向前的事件发送到家​​长的的onTouchEvent 方法通常的处理。它也可以返回,只是对事件的谍照他们的旅行下来视图层次结构,以他们一贯的目标。

您想要做的基本上是这样的 onInterceptTouchEvent 父视图,你检测甩:

ACTION_DOWN ,记录了触摸的位置。返回。 在 ACTION_MOVE ,检查初始触摸向下的位置和当前位置之间的增量。如果它是过去的一个阈值,(框架使用ViewConfiguration#getScaledTouchSlop()或者从 ViewConfiguration 其他合适的值这样的事情,)返回。 检测和处理的基础上的onTouchEvent 一扔像往常一样。

一旦拦截,在的ListView 将取消其触摸操控,你不会得到你的列表中的项目不需要的点击事件。 的ListView 也被设置为窃听事件禁止其母公司,一旦用户开始垂直滚动列表,这意味着你不会得到错误的水平甩如果用户草率甩清单垂直。

1个大神程序员 100个菜鸟程序员

这是像股票Android的启动或新闻和天气怎么办方的滚动/ tappable内容端分页。

I have a ListView inside of a ViewFlipper which I am flipping when the user swipes across the screen. Clicking on a ListView will open the browser. Sometimes when I am swiping, it gets detected as a touch on the ListView and will open the browser. This can be annoying. How can I prevent this from happening?

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;  
        }  

解决方案

The way this is normally done is through the parent view's onInterceptTouchEvent method. onInterceptTouchEvent has a chance to see any touch event before a view's children do. If onInterceptTouchEvent returns true the child view that was previously handling touch events receives an ACTION_CANCEL and the events from that point forward are sent to the parent's onTouchEvent method for the usual handling. It can also return false and simply spy on events as they travel down the view hierarchy to their usual targets.

You want to do essentially this in onInterceptTouchEvent on the parent view where you're detecting the flings:

On ACTION_DOWN, record the location of the touch. Return false. On ACTION_MOVE, check the delta between initial touch down position and current position. If it's past a threshold value, (the framework uses ViewConfiguration#getScaledTouchSlop() or other appropriate values from ViewConfiguration for things like this,) return true. Detect and handle the fling as usual based on onTouchEvent.

Once you intercept, the ListView will cancel its touch handling and you won't get unwanted tap events on your list items. ListView is also set up to disallow its parent from intercepting events once the user has started vertically scrolling the list, which means you won't get mistaken horizontal flings if the user sloppily flings the list vertically.

This is how things like the stock Android Launcher or News and Weather do side to side paging of scrolling/tappable content.