首页 > 解决方案 > 使用“V”形动画制作 ImageView

问题描述

我正在尝试将图像从右到左移动一个“V”(从上到下)。这是一张描述我所追求的图像: V形动画

我尝试使用ObjectAnimatorAnimatorSet但我没有得到我想要得到的东西。很难理解为什么我会得到别的东西。
这是我当前的代码:

/**
 * translateLeft = -160dp
 * translateDown = 25dp
 * translateUp   = -25dp
 */
private void vShapedAnimation () {
    AnimatorSet upDownSet = new AnimatorSet();
    AnimatorSet downUpSet = new AnimatorSet();
    AnimatorSet finalSet = new AnimatorSet();
    ObjectAnimator rightToLeft = ObjectAnimator.ofFloat(this.imageView, View.TRANSLATION_X, this.getResources().getDimensionPixelOffset(R.dimen.translateLeft) / 2);
    ObjectAnimator upDown = ObjectAnimator.ofFloat(this.imageView, View.TRANSLATION_Y, this.getResources().getDimensionPixelOffset(R.dimen.translateDown));
    ObjectAnimator downUp = ObjectAnimator.ofFloat(this.imageView, View.TRANSLATION_Y, this.getResources().getDimensionPixelOffset(R.dimen.translateUp));
    upDownSet.playTogether(
            rightToLeft,
            upDown
    );
    downUpSet.playTogether(
            rightToLeft,
            downUp
    );
    finalSet.playSequentially(
            upDownSet,
            downUpSet
    );
    finalSet.setDuration(300);
    finalSet.addListener(new Animator.AnimatorListener() {
        @Override
        public void onAnimationStart(Animator animation) {

        }

        @Override
        public void onAnimationEnd(Animator animation) {
            animation.removeListener(this);
            animation.setDuration(0);
            animation.setInterpolator(new ReverseInterpolator());
            animation.start();
        }

        @Override
        public void onAnimationCancel(Animator animation) {

        }

        @Override
        public void onAnimationRepeat(Animator animation) {

        }
    });
    finalSet.start();
}

来自ReverseInterpolator这里AnimatorListener

如何将 ObjectAnimator 重置为初始状态?

我打算同时旋转一下图像。如果“V”可以向内弯曲一点,那将是完美的。但是,如果一开始有人可以帮我做基本的动画,那将不胜感激。

标签: androidimageviewandroid-animationobjectanimatoranimatorset

解决方案


ObjectAnimator有它奇怪的时刻,但我终于掌握了它(至少足以解决我自己的问题)。

问题在于,在一系列动画中,最好始终指示开始位置和结束位置。在我写的问题中,这三ObjectAnimators个人只给出了结束位置。这使得动画从奇怪的地方开始。

使用伪代码示例,如果您想从 A 到 C 再经过 B,则需要将其写下来:

ObjectAnimator AtoB_X = ObjectAnimator.ofFloat(this.imageView, View.TRANSLATION_X, A.x, B.x - A.x);
ObjectAnimator BtoC_X = ObjectAnimator.ofFloat(this.imageView, View.TRANSLATION_X, B.x - A.x, C.x - A.x);
ObjectAnimator AtoB_Y = ObjectAnimator.ofFloat(this.imageView, View.TRANSLATION_Y, A.y, B.y - A.y);
ObjectAnimator BtoC_Y = ObjectAnimator.ofFloat(this.imageView, View.TRANSLATION_Y, B.y - A.y, C.y - A.y);

重要提示:始终使用dp测量值。切勿使用px测量值。这就是为什么在我的代码中,我使用this.getResources().getDimensionPixelOffset(). 它将dp值转换为px适合每个屏幕分辨率的值。

现在,对于我的工作代码:

private void vShapedAnimation() {
    AnimatorSet upDownSet = new AnimatorSet();
    AnimatorSet downUpSet = new AnimatorSet();
    AnimatorSet finalSet = new AnimatorSet();
    ObjectAnimator rightToHalf = ObjectAnimator.ofFloat(this.imageView, View.TRANSLATION_X, 0, this.getResources().getDimensionPixelOffset(R.dimen.translateLeft) / 2);
    ObjectAnimator halfToLeft = ObjectAnimator.ofFloat(this.imageView, View.TRANSLATION_X, this.getResources().getDimensionPixelOffset(R.dimen.translateLeft) / 2, this.getResources().getDimensionPixelOffset(R.dimen.translateLeft));
    ObjectAnimator upDown = ObjectAnimator.ofFloat(this.imageView, View.TRANSLATION_Y, 0, this.getResources().getDimensionPixelOffset(R.dimen.translateDown));
    ObjectAnimator downUp = ObjectAnimator.ofFloat(this.imageView, View.TRANSLATION_Y, this.getResources().getDimensionPixelOffset(R.dimen.translateDown), 0);
    upDownSet.playTogether(
            rightToHalf,
            upDown
    );
    downUpSet.playTogether(
            halfToLeft,
            downUp
    );
    finalSet.playSequentially(
            upDownSet,
            downUpSet
    );
    finalSet.setInterpolator(new LinearInterpolator());
    finalSet.setDuration(300);
    finalSet.start();
}

推荐阅读