9

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

Suragch
  • 484,302
  • 314
  • 1,365
  • 1,393
Sandy
  • 2,572
  • 7
  • 40
  • 61

1 Answers1

15

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.

monchote
  • 3,440
  • 2
  • 20
  • 20
  • In order not to re-draw the view so rapidly for every bit of the scroll, add a condition for distanceX. like this: `if(distanceX > 5){ marginLayoutParams.leftMargin = (int)marginLayoutParams.leftMargin - distanceX;` – Saba Jamalian Jun 12 '14 at 21:38
  • @monchote bro Your Code is working prefect ...I am using Button instead of Textview. I can able to drag the Button. When I take out my finger the button is return back the original position.I want to stay the button where I stop my finger around the RelativeLayout.Please help .. – reegan29 May 28 '15 at 07:24
  • 1
    @reegan29 Simply try not calling snapBack() from within onTouch. That should do it. – monchote May 29 '15 at 09:39
  • @monchote Hi, i also have to rotate the view with gestures. After i rotate the view >=90 degrees the scroll is getting weird. Its because the margin top and margin left is also rotating while i rotate the view. is there a work around for this issue?? – hushed_voice Sep 25 '17 at 05:46