Adding natural dragging effect to ImageView same as Facebook Messanger chat heads using Rebound library

android, animation, facebook, spring

Solution

what about this:

class V extends View implements SpringListener {
    private static final int NUM_ELEMS = 4;
    private Spring[] mXSprings = new Spring[NUM_ELEMS];
    private Spring[] mYSprings = new Spring[NUM_ELEMS];
    private Paint mPaint = new Paint();
    private Bitmap mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);

    public V(Context context) {
        super(context);
        SpringSystem ss = SpringSystem.create();

        Spring s;
        for (int i = 0; i < NUM_ELEMS; i++) {
            s = ss.createSpring();
            s.setSpringConfig(new MySpringConfig(200, i == 0? 8 : 15 + i * 2, i, true));
            s.addListener(this);
            mXSprings[i] = s;

            s = ss.createSpring();
            s.setSpringConfig(new MySpringConfig(200, i == 0? 8 : 15 + i * 2, i, false));
            s.addListener(this);
            mYSprings[i] = s;
        }
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        mXSprings[0].setCurrentValue(w / 2);
        mYSprings[0].setCurrentValue(0);

        mXSprings[0].setEndValue(w / 2);
        mYSprings[0].setEndValue(h / 2);
    }

    @Override
    public void onSpringActivate(Spring s) {
    }

    @Override
    public void onSpringAtRest(Spring s) {
    }

    @Override
    public void onSpringEndStateChange(Spring s) {
    }

    @Override
    public void onSpringUpdate(Spring s) {
        MySpringConfig cfg = (MySpringConfig) s.getSpringConfig();
        if (cfg.index < NUM_ELEMS - 1) {
            Spring[] springs = cfg.horizontal? mXSprings : mYSprings;
            springs[cfg.index + 1].setEndValue(s.getCurrentValue());
        }
        if (cfg.index == 0) {
            invalidate();
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        mXSprings[0].setEndValue(event.getX());
        mYSprings[0].setEndValue(event.getY());
        return true;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        for (int i = NUM_ELEMS - 1; i >= 0; i--) {
            mPaint.setAlpha(i == 0? 255 : 192 - i * 128 / NUM_ELEMS);
            canvas.drawBitmap(mBitmap, 
                    (float) mXSprings[i].getCurrentValue() - mBitmap.getWidth() / 2,
                    (float) mYSprings[i].getCurrentValue() - mBitmap.getHeight() / 2,
                    mPaint);
        }
    }

    class MySpringConfig extends SpringConfig {
        int index;
        boolean horizontal;
        public MySpringConfig(double tension, double friction, int index, boolean horizontal) {
            super(tension, friction);
            this.index = index;
            this.horizontal = horizontal;
        }
    }
}

Problem

I am developing one app where I am dragging around my ImageView in Activity. I have configured Facebook Rebound library for spring animation which is originally used in Facebook Messenger's chat heads animations. I want to add this kind of animations to my ImageView when I drag it. VIDEO So far I am able to get spring animation when I touch ImageView (implemented spring on rootview), this is my code. How can I implement that natural type of dragging effect to my ImageView. ``` public class MainTry extends Activity { int windowwidth; int windowheight; private LayoutParams layoutParams; private final BaseSpringSystem mSpringSystem = SpringSystem.create(); private FrameLayout mRootView; private Spring spring; private View mImageView; private VelocityTracker velocity = null; private float dx; private float dy; private View rootView; private ImageView img; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.layout); // Create a system to run the physics loop for a set of springs. SpringSystem springSystem = SpringSystem.create(); // Add a spring to the system. spring = springSystem.createSpring(); rootView = getWindow().getDecorView() .findViewById(android.R.id.content); windowwidth = getWindowManager().getDefaultDisplay().getWidth(); windowheight = getWindowManager().getDefaultDisplay().getHeight(); img = (ImageView) findViewById(R.id.imageView2); rootView.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: // spring.setEndValue(1); break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: // spring.setEndValue(0); break; } return true; } }); // Add a listener to observe the motion of the spring. spring.addListener(new SimpleSpringListener() { @Override public void onSpringUpdate(Spring spring) { // You can observe the updates in the spring // state by asking its current value in onSpringUpdate. float value = (float) spring.getCurrentValue(); float scale = .5f - (value * 0.1f); img.setScaleX(scale); img.setScaleY(scale); } }); // spring.setEndValue(1); img.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { LayoutParams layoutParams = (LayoutParams) img .getLayoutParams(); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: dx = event.getRawX() - 10; dy = event.getRawY() - 10; if (velocity == null) { // Retrieve a new VelocityTracker object to watch the // velocity of a motion. velocity = VelocityTracker.obtain(); } else { // Reset the velocity tracker back to its initial state. velocity.clear(); } break; case MotionEvent.ACTION_MOVE: dx = event.getRawX() - 10; dy = event.getRawY() - 10; velocity.addMovement(event); spring.setVelocity(velocity.getYVelocity()); spring.setCurrentValue(dy); spring.setEndValue(dy); layoutParams.leftMargin = (int) dx - 10; layoutParams.topMargin = (int) dy - 10; img.setLayoutParams(layoutParams); break; case MotionEvent.ACTION_CANCEL: break; case MotionEvent.ACTION_UP: velocity.addMovement(event); spring.setVelocity(velocity.getYVelocity()); spring.setCurrentValue(event.getRawY() - 10); spring.setEndValue(0); break; default: break; } return true; } }); } @Override public void onResume() { super.onResume(); } @Override public void onPause() { super.onPause(); } } ```

Original source