Search code examples
androidobjectanimator

Why the location of view always resets after I use ObjectAnimator to View.TRANSLATION_X?


I created a simple app, just want when I click a button, the imageview will travel to another position.

Below is the code, but it seems that when I click the button, the imageview always begin with the original position, not the real position. Is there any problem with my code?

public class MainActivity extends Activity{

private ImageView iv;
private Button bt;
private AnimatorSet mAniSet;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.ddd);
    iv = (ImageView) this.findViewById(R.id.imageView1);
    bt = (Button) this.findViewById(R.id.button1);
    mAniSet = new AnimatorSet();

    bt.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {

            int pointOnScreen[] = new int[2];
            iv.getLocationOnScreen(pointOnScreen);

            ObjectAnimator AniTranslationX = ObjectAnimator.ofFloat(iv, View.TRANSLATION_X, pointOnScreen[0]+100);
            mAniSet.playTogether(AniTranslationX);
            mAniSet.setTarget(iv);
            mAniSet.setDuration(200).start();
        }           
    });
}

}


Solution

  • If you create a ObjectAnimator.ofFloat(Object, Property, values) and there is only one value, so the origin of the animation will be 0f.

    You can find the source into the class android.animation.KeyFrameSet and the following method:

    public static KeyframeSet ofFloat(float... values) {
            boolean badValue = false;
            int numKeyframes = values.length;
            FloatKeyframe keyframes[] = new FloatKeyframe[Math.max(numKeyframes,2)];
            if (numKeyframes == 1) {
                keyframes[0] = (FloatKeyframe) Keyframe.ofFloat(0f);
                keyframes[1] = (FloatKeyframe) Keyframe.ofFloat(1f, values[0]);
                if (Float.isNaN(values[0])) {
                    badValue = true;
                }
            } else {
                keyframes[0] = (FloatKeyframe) Keyframe.ofFloat(0f, values[0]);
                for (int i = 1; i < numKeyframes; ++i) {
                    keyframes[i] =
                            (FloatKeyframe) Keyframe.ofFloat((float) i / (numKeyframes - 1), values[i]);
                    if (Float.isNaN(values[i])) {
                        badValue = true;
                    }
                }
            }
            if (badValue) {
                Log.w("Animator", "Bad value (NaN) in float animator");
            }
            return new FloatKeyframeSet(keyframes);
        }
    

    You can see, with only one value, the start of the animation is 0f (keyframes[0]).

    If you put 2 values, your animation will start from the first value and stop at the second:

    ObjectAnimator AniTranslationX = ObjectAnimator.ofFloat(iv, View.TRANSLATION_X, pointOnScreen[0], pointOnScreen[0] + 100);
    

    With 3 or more values, the animation will reach all these values over the time of the animation.