Search code examples
androidandroid-event

How can I detect the onFling event in Android?


Based on various examples I've found around the internet, I've got this as my code to pick up "swipes" (onFling AFAICT)

However the only event handler that seems to be called is the onTouchEvent of GameView itself. I'm getting the messages logged by it.

Even though, inside it, I'm then calling gestureDetector.onTouchEvent(event), nothing seems to be calling SimpleOnGestureListener's own onFling event. Nor does the listener return true, and so I'm not seeing the message "back from gestureDetector".

Nor, again, are any of the other events on the GameView being triggered. This includes GameView's own "onFling" event.

So I presume I'm missing a crucial bit of wiring here. Either setting a listener or telling something else to call something else. But I can't find examples of it.

public class GameView extends android.view.SurfaceView  implements SurfaceHolder.Callback, GestureDetector.OnGestureListener {
    private static final String DEBUG_TAG = "XXXX";
    private MainThread thread;
    private GestureDetector gestureDetector;

    public GameView(Context context) {
        super(context);
        getHolder().addCallback(this);
        thread = new MainThread(getHolder(), this);
        setFocusable(true);
        gestureDetector = new GestureDetector(context,
                new GestureDetector.SimpleOnGestureListener() {


                    @Override
                public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
                    Log.d(DEBUG_TAG,"GestureListener onFling");

                    // Get the x and y distance of the swipe
                    float deltaX = e2.getX() - e1.getX();
                    float deltaY = e2.getY() - e1.getY();

                    // Check if the swipe was horizontal or vertical
                    if (Math.abs(deltaX) > Math.abs(deltaY)) {
                        // Swipe was horizontal, check if it was left or right
                        if (deltaX > 0) {
                             Log.d(DEBUG_TAG,"right");
                        } else {
                            Log.d(DEBUG_TAG,"left");
                        }
                    } else {
                        // Swipe was vertical, check if it was up or down
                        if (deltaY > 0) {
                            Log.d(DEBUG_TAG,"down");
                        } else {
                            Log.d(DEBUG_TAG,"up");
                        }
                    }
                    return true;
                }

        });
    }

    ...

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        Log.d(DEBUG_TAG,"onTouchEvent " + getActionMasked(event));

        if (gestureDetector.onTouchEvent(event)) {
            Log.d(DEBUG_TAG,"back from gestureDetector");
            return true;
        }
        Log.d(DEBUG_TAG,"end" );

        return super.onTouchEvent(event);
    }


    @Override
    public boolean onDown(MotionEvent event) {
        Log.d(DEBUG_TAG,"onDown: " + event.toString());
        return true;
    }

    @Override
    public boolean onFling(MotionEvent event1, MotionEvent event2,
                           float velocityX, float velocityY) {
        Log.d(DEBUG_TAG, "onFling: " + event1.toString() + event2.toString());   
        return true;
    }

    @Override
    public void onLongPress(MotionEvent event) {
        Log.d(DEBUG_TAG, "onLongPress: " + event.toString());
    }

    @Override
    public boolean onScroll(MotionEvent event1, MotionEvent event2, float distanceX, float distanceY) {
        Log.d(DEBUG_TAG, "onScroll: " + event1.toString() + event2.toString());
        return true;
    }

    @Override
    public void onShowPress(MotionEvent event) {
        Log.d(DEBUG_TAG, "onShowPress: " + event.toString());
    }

    @Override
    public boolean onSingleTapUp(MotionEvent event) {
        Log.d(DEBUG_TAG, "onSingleTapUp: " + event.toString());
        return true;
    }
}

Solution

  • From the documentation

    Whether or not you use GestureDetector.OnGestureListener, it's best practice to implement an onDown() method that returns true. This is because all gestures begin with an onDown() message. If you return false from onDown(), as GestureDetector.SimpleOnGestureListener does by default, the system assumes that you want to ignore the rest of the gesture, and the other methods of GestureDetector.OnGestureListener never get called. This has the potential to cause unexpected problems in your app. The only time you should return false from onDown() is if you truly want to ignore an entire gesture.

    Therefore, override onDown() in your listener and return true there.