如何在Android上动画化视图的背景颜色变化?

例如:

我有一个红色背景色的视图。视图的背景颜色变为蓝色。我怎样才能在颜色之间平滑过渡呢?

如果视图不能做到这一点,那么另一种选择是受欢迎的。


当前回答

你可以使用API 11上面的ArgbEvaluatorCompat类。

implementation 'com.google.android.material:material:1.0.0' 


ValueAnimator colorAnim = ValueAnimator.ofObject(new ArgbEvaluatorCompat(), startColor, endColor);
colorAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            mTargetColor = (int) animation.getAnimatedValue();
        }
    });
colorAnim.start();

其他回答

这里有一个很好的函数可以做到这一点:

public static void animateBetweenColors(final @NonNull View viewToAnimateItsBackground, final int colorFrom,
                                        final int colorTo, final int durationInMs) {
    final ColorDrawable colorDrawable = new ColorDrawable(durationInMs > 0 ? colorFrom : colorTo);
    ViewCompat.setBackground(viewToAnimateItsBackground, colorDrawable);
    if (durationInMs > 0) {
        final ValueAnimator colorAnimation = ValueAnimator.ofObject(new ArgbEvaluator(), colorFrom, colorTo);
        colorAnimation.addUpdateListener(animator -> {
            colorDrawable.setColor((Integer) animator.getAnimatedValue());
            ViewCompat.setBackground(viewToAnimateItsBackground, colorDrawable);
        });
        colorAnimation.setDuration(durationInMs);
        colorAnimation.start();
    }
}

在Kotlin中:

@JvmStatic
fun animateBetweenColors(viewToAnimateItsBackground: View, colorFrom: Int, colorTo: Int, durationInMs: Int) {
    val colorDrawable = ColorDrawable(if (durationInMs > 0) colorFrom else colorTo)
    ViewCompat.setBackground(viewToAnimateItsBackground, colorDrawable)
    if (durationInMs > 0) {
        val colorAnimation = ValueAnimator.ofObject(ArgbEvaluator(), colorFrom, colorTo)
        colorAnimation.addUpdateListener { animator: ValueAnimator ->
            colorDrawable.color = (animator.animatedValue as Int)
            ViewCompat.setBackground(viewToAnimateItsBackground, colorDrawable)
        }
        colorAnimation.duration = durationInMs.toLong()
        colorAnimation.start()
    }
}

在Kotlin中使用以下函数:

private fun animateColorValue(view: View) {
    val colorAnimation =
        ValueAnimator.ofObject(ArgbEvaluator(), Color.GRAY, Color.CYAN)
    colorAnimation.duration = 500L
    colorAnimation.addUpdateListener { animator -> view.setBackgroundColor(animator.animatedValue as Int) }
    colorAnimation.start()
}

传递任何你想改变颜色的视图。

我最终想出了一个(非常好的)解决这个问题的方法!

你可以使用TransitionDrawable来完成这个任务。例如,在可绘制文件夹中的XML文件中,你可以这样写:

<?xml version="1.0" encoding="UTF-8"?>
<transition xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- The drawables used here can be solid colors, gradients, shapes, images, etc. -->
    <item android:drawable="@drawable/original_state" />
    <item android:drawable="@drawable/new_state" />
</transition>

然后,在实际视图的XML中,你会在android:background属性中引用这个TransitionDrawable。

在这一点上,你可以在你的代码中执行以下命令来启动转换:

TransitionDrawable transition = (TransitionDrawable) viewObj.getBackground();
transition.startTransition(transitionTime);

或者反向运行转换,调用:

transition.reverseTransition(transitionTime);

请参阅Roman使用属性动画API的另一个解决方案的答案,在这个答案最初发布时还不可用。

关于XML驱动动画的文档非常糟糕。我已经搜索了大约几个小时,只是为了在按下按钮时使背景颜色动画化…遗憾的是动画只有一个属性:你可以在选择器中使用exitFadeDuration:

<selector xmlns:android="http://schemas.android.com/apk/res/android"
    android:exitFadeDuration="200">

    <item android:state_pressed="true">
        <shape android:tint="#3F51B5" />
    </item>

    <item>
        <shape android:tint="#F44336" />
    </item>

</selector>

然后将它用作视图的背景。不需要Java/Kotlin代码。

基于ademar111190的答案,我创建了这个方法,它将在任意两种颜色之间脉冲视图的背景颜色:

private void animateBackground(View view, int colorFrom, int colorTo, int duration) {


    ObjectAnimator objectAnimator = ObjectAnimator.ofObject(view, "backgroundColor", new ArgbEvaluator(), colorFrom, colorTo);
    objectAnimator.setDuration(duration);
    //objectAnimator.setRepeatCount(Animation.INFINITE);
    objectAnimator.addListener(new Animator.AnimatorListener() {
        @Override
        public void onAnimationStart(Animator animation) {

        }

        @Override
        public void onAnimationEnd(Animator animation) {
            // Call this method again, but with the two colors switched around.
            animateBackground(view, colorTo, colorFrom, duration);
        }

        @Override
        public void onAnimationCancel(Animator animation) {

        }

        @Override
        public void onAnimationRepeat(Animator animation) {

        }
    });
    objectAnimator.start();
}