28
votes

My question is simple, where's the onUp event when implementing a GestureListener?

I has a lot of events on the gesturedetector, and cannot just consume the onUp event of the listener, cause one of events are the onSingleTapConfirmed that needs it.

4
I'm not entirely sure what do you want to do here, but there is onSingleTapUp in GestureListener that might be what you are looking for. It is fired on a complete tap, though, not swiping. For that you could just process the "raw" onTouchEvent of view/activity without passing it to GestureDetector.Xion
onSingleTapUp is fired when a tap is done. I need DOWN, then MOVE, and end with UP.Marcos Vasconcelos
That's onFling, except that you don't get the MOVE events. If you need them, I guess your only option is to handle onTouchEvent directly.Xion
Hey @MarcosVasconcelos. I see that you solved this somehow? I'm trying to do the same thing and onFling() doesn't work for me as the below answer suggests. Can you explain how you fixed this? Thanks.shoke
Use the onTouchEvent approach.Marcos Vasconcelos

4 Answers

26
votes

Try using onFling(). Seems like a weird name but for me, it works as the onUp() method would logically work. Or try this method...

@Override
public boolean onTouchEvent(MotionEvent me) {

  Log.v("ADAM", "ontouch: " + me.getAction());

  if(me.getAction() == 0){
    Log.v("ADAM", "Down");
  }
  else if (me.getAction() == 1) {
    Log.v("ADAM", "Up");
  }
  else if (me.getAction() == 2) {
    Log.v("ADAM", "Scroll");
  }
  boolean detectedUp = event.getAction() == MotionEvent.ACTION_UP;
  if (!mGestureDetector.onTouchEvent(event) && detectedUp) {
    return onUp(event);
  }
  return true;
}
8
votes

I fixed it by reading the Action event before I pass it to the GestureListener

img.setOnTouchListener(new OnTouchListener() {
    @Override
    public boolean onTouch(View arg0, MotionEvent arg1) {
      if (arg1.getAction() == MotionEvent.ACTION_UP
          && !getDocument().isScaled()) 
        img.notifyUp();
      return gestures.onTouchEvent(arg1);
    }
});
6
votes

The other answers can solve the question,maybe they work good,but I don't think those are good solutions.
Because we should deal with the event in a single moudle,so that we can be esaier to maintain or expand the code.
(By the way, don not use onFilng() ,if your finger move slowly on the screen,onFilng() wouldn't work)
So,my solution is rewriting the GestureDetector:

public class ModifyGestureDetector extends GestureDetector {

    MyGestureListener myGestureListener;

    public ModifyGestureDetector(Context context, OnGestureListener listener) {
        super(context, listener);
        init(listener);
    }

    void init(OnGestureListener listener){
        if (listener instanceof MyGestureListener){
            myGestureListener = (MyGestureListener) listener;
        }
    }

    //u can write something more complex as long as u need
    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        if(ev.getAction() == MotionEvent.ACTION_UP 
            && myGestureListener != null){
            myGestureListener.onUp(ev);
        }
        return super.onTouchEvent(ev);
    }

    public interface MyGestureListener{
        public void onUp(MotionEvent ev);
    }
}  

And the listener:

public class MyGestureListener extends GestureDetector.SimpleOnGestureListener
        implements ModifyGestureDetector.MyGestureListener {


    @Override
    public void onUp(MotionEvent ev) {
        //do what u want
    }
} 

: )

2
votes

Have you returned true from the other events you consume in your GestureDetector.OnGestureListener? I had this problem and it turns out if you return false, the system assumes you aren't interested and stops passing you events, so you miss the up!