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
.
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);
}