How to distinguish between throw and touch?

I have a ListView inside the ViewFlipper, which I flip when the user views the screen. Clicking on ListView will open a browser. Sometimes, when I browse, it shows up as a tap on the ListView and opens the browser. This can be annoying. How can I prevent this?

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
source share
2 answers

This is usually done through the parent method onInterceptTouchEvent . onInterceptTouchEvent has the ability to see some kind of touch event before children make the view. If onInterceptTouchEvent returns true child view that previously handled touch events receives ACTION_CANCEL , and events from this point forward are sent to the parent onTouchEvent method for normal processing. It can also return false and simply track events when they move down the view hierarchy to their usual goals.

You want to do this essentially in onInterceptTouchEvent in the parent view, where you detect pop-ups:

  • In ACTION_DOWN record the location of the touch. Return false .
  • In ACTION_MOVE , check the delta between the initial touch down and the current position. If it passes the threshold (the structure uses ViewConfiguration#getScaledTouchSlop() or other appropriate values ​​from ViewConfiguration for things like this,) return true .
  • onTouchEvent detection and control, as usual, is based on onTouchEvent .

Once you intercept, ListView will cancel touch processing and you will not receive unwanted tap events in your lists. ListView also configured to prevent its parent process from catching events as soon as the user starts scrolling vertically in the list, which means that you won’t be mistaken for horizontal throws if the user sloppily displays the list vertically.

This is how things like Android Launcher or News and Weather do side-swipe scroll / swap content.

+12
source

Have you tried using SimpleOnGestureListener.onSingleTapConfirmed (MotionEvent) for a "click" event? This will be called only after the detector is sure that the user first pressed the button, and not double-clicking (or, hopefully, resetting).

 class MyGestureDetector extends SimpleOnGestureListener { @Override public boolean onSingleTapConfirmed(MotionEvent event) { // Code... } } 
+1
source

All Articles