Home > Software engineering >  How to correctly scale and move an ImageView to an absolute position using ObjectAnimator
How to correctly scale and move an ImageView to an absolute position using ObjectAnimator

Time:05-23

I am trying to move an ImageView after scaling it down, but for some reason, the position does not match the destinated position. First I calculate the scaling factors and the difference between the new and old positions. Then I started the animation, but the ImageView moves to far to the left and to the bottom and I have no clue why.

float scaleX = (destWidth * 1.0f) / imageView.getMeasuredWidth();
float scaleY = (destHeight * 1.0f) / imageView.getMeasuredHeight();
float moveX = -1 * (imageView.getLeft() - destX);   // move image to the left
float moveY = destY - imageView.getTop();           // move image to the bottom

oa = ObjectAnimator.ofPropertyValuesHolder(imageView
        , PropertyValuesHolder.ofFloat("scaleX", scaleX)
        , PropertyValuesHolder.ofFloat("scaleY", scaleY)
        , PropertyValuesHolder.ofFloat("translationX", moveX)
        , PropertyValuesHolder.ofFloat("translationY", moveY));

oa.setDuration(3000);
oa.setRepeatMode(ValueAnimator.REVERSE);
oa.setRepeatCount(ValueAnimator.INFINITE);
oa.start();

CodePudding user response:

I figured it out myself, but I will leave the corrected code below for others with similar problems.

Basically, the ImageView is first moved according to the translation and then scaled down. The scaling moves the top, bottom, left and right to the center and therefore the ImageView is offset.

To fix this half of the difference between the old ImageView size and the new ImageView size needs to be subtracted from the previous moveX/moveY.

float moveX = -1 * (imageView.getLeft() - destX) 
          - ((imageView.getMeasuredWidth() - (imageView.getMeasuredWidth() * scaleX)) / 2);
// move image to the bottom   
float moveY = destY - imageView.getTop() 
          - ((imageView.getMeasuredHeight() - (imageView.getMeasuredHeight() * scaleY)) / 2);           

Finally, the finished code should look like this.

float scaleX = (destWidth * 1.0f) / imageView.getMeasuredWidth();
float scaleY = (destHeight * 1.0f) / imageView.getMeasuredHeight();
// move image to the left
float moveX = -1 * (imageView.getLeft() - destX) 
          - ((imageView.getMeasuredWidth() - (imageView.getMeasuredWidth() * scaleX)) / 2);
// move image to the bottom   
float moveY = destY - imageView.getTop() 
          - ((imageView.getMeasuredHeight() - (imageView.getMeasuredHeight() * scaleY)) / 2);           

oa = ObjectAnimator.ofPropertyValuesHolder(imageView
        , PropertyValuesHolder.ofFloat("scaleX", scaleX)
        , PropertyValuesHolder.ofFloat("scaleY", scaleY)
        , PropertyValuesHolder.ofFloat("translationX", moveX)
        , PropertyValuesHolder.ofFloat("translationY", moveY));

oa.setDuration(3000);
oa.setRepeatMode(ValueAnimator.REVERSE);
oa.setRepeatCount(ValueAnimator.INFINITE);
oa.start();
  • Related