Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Long press in GestureDetector also fires on tap

I tried implementing code from this question: Detecting a long press with Android, but it always detects a long press, if even I just tap it. My code is as follows (I extended ImageView, because more code is in it, not relevant for this question):

public class EbsImageView extends ImageView  {
    final GestureDetector gestureDetector = new GestureDetector(this.getContext(), new GestureDetector.SimpleOnGestureListener() {
        public void onLongPress(MotionEvent e) {
            Log.e("", "Longpress detected");
        }
    public boolean onSingleTapUP(MotionEvent e) {
        Log.e("", "Press detected");

            // don't consume, we want the long press to fire if it was a 
            // long press
        return false;
        }
    });

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        return gestureDetector.onTouchEvent(event);
    }
}
like image 860
Bart Friederichs Avatar asked Jun 20 '14 11:06

Bart Friederichs


3 Answers

You need to override onDown and make it return true. The following code worked for me:

class SimpleGestureListener extends GestureDetector.SimpleOnGestureListener {

    @Override
    public boolean onDown(MotionEvent event) {
      // triggers first for both single tap and long press
      return true;
    }

    @Override
    public boolean onSingleTapUp(MotionEvent event) {
      // triggers after onDown only for single tap
      return true;
    }

    @Override
    public void onLongPress(MotionEvent event) {
      // triggers after onDown only for long press
      super.onLongPress(event);
    }
}
like image 181
arudoy Avatar answered Oct 08 '22 17:10

arudoy


Solution above works (returning true in onDown()). I have also made it work by setting clickable and focusable property of View to true before setting GestureDetector.

val gestureDetectorCompat = GestureDetectorCompat(context, object : GestureDetector.SimpleOnGestureListener() {
        override fun onSingleTapConfirmed(e: MotionEvent?): Boolean {
            // log "Single Tap Confirm"
            return true
        }

        override fun onLongPress(e: MotionEvent?) {
            // log "Long Press"
        }
    })
image_stateful.isClickable = true
image_stateful.isFocusable = true
image_stateful.setOnTouchListener { _, event -> gestureDetectorCompat.onTouchEvent(event) }
like image 25
Jemshit Iskenderov Avatar answered Oct 08 '22 16:10

Jemshit Iskenderov


As I mention in my comment, you should distinguish between onSingleTapUp() and onSingleTapUP(). Using the Override annotation is a good practice.

I'm a bit confused because the title of your question seems to indicate that a long press also fires the on tap event, while the text of your question says it the other way around. That is that a tap fires a long press event. If the later is the case, try returning true from your onSingleTapUp(). This works for me using the SimpleGestureListener:

class SimpleGestureListener extends GestureDetector.SimpleOnGestureListener {

  @Override
  public boolean onDown(MotionEvent event) {
     //...
    return super.onDown(event);
  }

  @Override
  public boolean onSingleTapUp(MotionEvent event) {
    //...
    return true;
  }

  @Override
  public void onLongPress(MotionEvent event) {
    //...
    super.onLongPress(event);
  }
}

I hope it helps.

like image 40
tomorrow Avatar answered Oct 08 '22 16:10

tomorrow