Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make a View follow my finger using onScroll and GestureDetector - Android

I have a RelativeLayout with a TextView in the middle. I've got it to detect onFling, onDown, and onScroll events using SimpleOnGestureListener().

I would like the TextView to follow my finger around the screen (can be just in the x axis), and when I lift my finger for it so animate either out of the screen or back to the middle (depending on how far I've moved it).

like image 612
Sandy Avatar asked Feb 04 '12 01:02

Sandy


People also ask

What is onFling?

onFling: is that the user lifts his finger in the end of the movement (that is the reason for what onFling is called one time).

What is onShowPress?

onShowPress The user has performed a down MotionEvent and not performed a move or up yet. This event is commonly used to provide visual feedback to the user to let them know that their action has been recognized i.e. highlight an element.

What does the GestureDetector Ongesturelistener interface do when implemented?

GestureDetector. SimpleOnGestureListener provides an implementation for all of the on<TouchEvent> methods by returning false for all of them. Thus you can override only the methods you care about. For example, the snippet below creates a class that extends GestureDetector.


1 Answers

This is what I normally do in these cases.

First of all, your onScroll method should look something like this:

@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY)
{
    // Make sure that mTextView is the text view you want to move around

    if (!(mTextView.getLayoutParams() instanceof MarginLayoutParams))
    {
        return false;
    }

    MarginLayoutParams marginLayoutParams = (MarginLayoutParams) mTextView.getLayoutParams();

    marginLayoutParams.leftMargin = (int) marginLayoutParams.leftMargin - distanceX;
    marginLayoutParams.topMargin = (int) marginLayoutParams.topMargin - distanceY;

    mTextView.requestLayout();

    return true;
}

We are modifying the leftMargin and topMargin an amount equivalent to the distance that has been scrolled.

Next, to make the text view animate back to its original position you need to do so when the the event is ACTION_UP or ACTION_CANCEL:

@Override
public boolean onTouch(View arg0, MotionEvent event)
{
    if (event.getActionMasked() == MotionEvent.ACTION_UP || event.getActionMasked() == MotionEvent.ACTION_CANCEL)
    {
        snapBack();
    }
    return mScrollDetector.onTouchEvent(event);
}

Then in the snapBack method we animate back the text view:

private void snapBack ()
{
    if (mTextView.getLayoutParams() instanceof MarginLayoutParams)
    {
        final MarginLayoutParams marginLayoutParams = (MarginLayoutParams) mTextView.getLayoutParams();

        final int startValueX = marginLayoutParams.leftMargin;
        final int startValueY = marginLayoutParams.topMargin;
        final int endValueX = 0;
        final int endValueY = 0;

        mTextView.clearAnimation();

        Animation animation = new Animation()
        {
            @Override
            protected void applyTransformation(float interpolatedTime, Transformation t)
            {
                int leftMarginInterpolatedValue = (int) (startValueX + (endValueX - startValueX) * interpolatedTime);
                marginLayoutParams.leftMargin = leftMarginInterpolatedValue;

                int topMarginInterpolatedValue = (int) (startValueY + (endValueY - startValueY) * interpolatedTime);
                marginLayoutParams.topMargin = topMarginInterpolatedValue;

                mTextView.requestLayout();
            }
        };
        animation.setDuration(200);
        animation.setInterpolator(new DecelerateInterpolator());
        mTextView.startAnimation(animation);
    }
}

And that should do! You can modify the endValueX and endValueY variables to control where the text view goes back when you lift your finger.

like image 73
monchote Avatar answered Nov 15 '22 16:11

monchote