22

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);
    }
}
Community
  • 1
  • 1
Bart Friederichs
  • 33,050
  • 15
  • 95
  • 195
  • return false from onTouchEvent() – Parth Kapoor Jun 20 '14 at 11:56
  • 1
    @Eu.Dr. makes no difference, I also tried the code from here: http://developer.android.com/training/gestures/detector.html but the same problem. – Bart Friederichs Jun 20 '14 at 12:14
  • where is Your @Override annotation at onLongPress and onSingleTapUp? It´s just a copy/paste fail? – Opiatefuchs Jun 20 '14 at 12:23
  • @Opiatefuchs they are not there, but even if I put them there, it doesn't work. – Bart Friederichs Jun 20 '14 at 12:24
  • I think You should return true from onSingleTapUp – Opiatefuchs Jun 20 '14 at 12:28
  • 1
    @Opiatefuchs onSingleTapUp isn't even fired at all. From the example from the Android docs, only `onDown`, `onShowPress` and `onLongPress` are fired. Always, whatever gesture I make. I am now working on a solution that uses the `View`'s `onLongClickListener`. – Bart Friederichs Jun 20 '14 at 12:31
  • ok, have You tried to use OnGestureListener instead of SimpleOnGestureListener? Like described in the API for SimpleOnGestureListener: "does nothing and return false for all applicable methods. " – Opiatefuchs Jun 20 '14 at 12:39
  • 3
    onSingleTapUp can't be fired as you don't override it. Instead you add a method onSingleTapUP. Note the last letter (P) should be lowercase while yours is uppercase, which does matter in JAVA. That's why @Opiatefuchs asked you about the Override annotation. If you add it, the compiler should warn you that you're actually not overriding. – tomorrow Jun 20 '14 at 13:09

3 Answers3

29

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);
    }
}
Suragch
  • 484,302
  • 314
  • 1,365
  • 1,393
arudoy
  • 561
  • 1
  • 6
  • 8
5

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) }
Jemshit
  • 9,501
  • 5
  • 69
  • 106
1

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.

Sufian
  • 6,405
  • 16
  • 66
  • 120
tomorrow
  • 1,260
  • 1
  • 14
  • 26