如何使用ValueAnimator在Android中创建Accelerate - Linear - Decelerate动画效果?

时间:2016-06-13 08:59:29

标签: android animation

现在我必须创建旋转风扇的动画。当用户点击POWER ON按钮时,此风扇开始旋转,然后将其旋转速度保持在某个水平。当用户单击POWER OFF按钮时,它会减慢然后停止。

我制作了如下代码:

ImageView mFanImageview;
private ValueAnimator mFanValueAnimator;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_centripetal_particle);
    ButterKnife.bind(this);
}

private void startFan() {
    mFanValueAnimator = new ValueAnimator();
    mFanValueAnimator.setDuration(1000);
    mFanValueAnimator.setFloatValues(mFanImageview.getRotation(), mFanImageview.getRotation() + 360);
    mFanValueAnimator.setInterpolator(new AccelerateInterpolator());
    mFanValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            mFanImageview.setRotation((Float) animation.getAnimatedValue());
        }
    });
    mFanValueAnimator.addListener(new AnimatorListenerAdapter() {
        @Override
        public void onAnimationEnd(Animator animation) {
            mFanValueAnimator = new ValueAnimator();
            mFanValueAnimator.setDuration(500);
            mFanValueAnimator.setFloatValues(mFanImageview.getRotation(), mFanImageview.getRotation() + 360);
            mFanValueAnimator.setRepeatCount(ValueAnimator.INFINITE);
            mFanValueAnimator.setRepeatMode(ValueAnimator.RESTART);
            mFanValueAnimator.setInterpolator(new LinearInterpolator());
            mFanValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                    mFanImageview.setRotation((Float) animation.getAnimatedValue());
                }
            });
            mFanValueAnimator.addListener(new AnimatorListenerAdapter() {
                @Override
                public void onAnimationCancel(Animator animation) {
                    stopFanValueAnimator().start();
                }
            });
            mFanValueAnimator.start();
        }

        @Override
        public void onAnimationCancel(Animator animation) {
            stopFanValueAnimator().start();
        }
    });
    mFanValueAnimator.start();
}

private ValueAnimator stopFanValueAnimator() {
    ValueAnimator stopAnimator = new ValueAnimator();
    stopAnimator.setDuration(1000);
    stopAnimator.setFloatValues(mFanImageview.getRotation(), mFanImageview.getRotation() + 360);
    stopAnimator.setInterpolator(new DecelerateInterpolator());
    stopAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            mFanImageview.setRotation((Float) animation.getAnimatedValue());
        }
    });
    return stopAnimator;
}

@OnClick(R.id.stop_button)
public void onStopButtonClicked() {
    mFanValueAnimator.cancel();
}

@OnClick(R.id.start_button)
public void onStartButtonClicked() {
    startFan();
}

上面的动画似乎没问题,但我发现AccelerateInterpolator动画师结束时的风扇旋转速度很难与LinearInterpolator的开头匹配。我必须仔细调整LinearInterpolator动画师的持续时间。

如何在AccelerateInterpolator动画师结束时获得更新率,然后设置LinearInterpolator动画师的正确持续时间?

1 个答案:

答案 0 :(得分:0)

我认为最好的方法是先设置加速插补器,然后重复设置LinearInterpolator。现在在重复的情况下放置一个标志来处理关闭。如果需要关闭开关,则更改开关关闭标志的值,该标志将应用减速插补器并确保动画不会再次运行。

mFanValueAnimator.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationRepeat(Animator animation) {
                if (switchOff) {
                    animation.setInterpolator(new DecelerateInterpolator());
                } else {
                    animation.setInterpolator(new LinearInterpolator());
                }
            }
        });