Search code examples
androidgesturelistener

Is it possible to override SimpleOnGestureListener to detect release?


I am trying to implement a gesture handler that allows the user to swipe in a parabolic shape (the way your fingers move if you swipe single handed).

I have been able to implement this by using the overriding the onDown and onScroll methods like this:

public class MoveViewTouchListener
        implements View.OnTouchListener
{
    public GestureDetector mGestureDetector;
    public View mView;
    public double a;
    public double b;
    public double c;


    public MoveViewTouchListener(View view,double a, double b, double c)
    {
        mGestureDetector = new GestureDetector(view.getContext(), mGestureListener);
        mView = view;
        this.a = a;
        this.b = b;
        this.c = c;

    }

    @Override
    public boolean onTouch(View v, MotionEvent event)
    {

        return mGestureDetector.onTouchEvent(event);

    }

    private GestureDetector.OnGestureListener mGestureListener = new GestureDetector.SimpleOnGestureListener()
    {
        private float mMotionDownX, mMotionDownY;

        @Override
        public boolean onDown(MotionEvent e)
        {

            mMotionDownX = e.getRawX() - mView.getTranslationX();
            mMotionDownY = e.getRawY() - mView.getTranslationY();
            return true;
        }

        @Override
        public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY)
        {
            mView.setTranslationX(e2.getRawX() - mMotionDownX);

            // Set the x translation
            double x = mView.getTranslationX();

            // Graphing quadratic (parabola)
            // y = ax^2 + bx + c

            double a = 0.00125;
            double b = 0.0;
            double c = 0.0;

            //Converting that to code
            double y = a*x*x + b*x + c;

            Log.d("Chex ","X = " + x +", Y = " + y);

            // Set the y translation
            mView.setTranslationY((float)y);

            return true;
        }

    };
}

Basically for every scroll event in the x direction I move set the translation in y direction.

This works great and swipes in the parabolic (quadratic) shape. But when the user doesn't swipe the full way across the screen I want to animate the icon back to the start position (Like what happens in tinder if you don't swipe the full way across).

I know I need to use MotionEvent.ACTION_UP but I don't see how I can use that in my case because I am making the changes in onScroll and onDown.


Solution

  • As far as I understand mGestureDetector handles the event only because the event is being delegated by MoveViewTouchListener.

    So, can't you simply check in MoveViewTouchListener::onTouch() if the event is a MotionEvent.ACTION_UP: in which case do not call mGestureDetector.onTouchEvent(event);, but simply animate the view back like (e.g:)

    mView.animate()
        .x(mViewInitialX)
        .y(mViewInitialY)
        .setDuration(200)
        .start();
    

    and return true.

    It would become something like

    @Override
    public boolean onTouch(View v, MotionEvent event) {
    
        if (event.getAction() == MotionEvent.EVENT_UP) {
            // go back to initial position
            return true;
        }
    
        return mGestureDetector.onTouchEvent(event);
    
    }