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

例如:

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

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


当前回答

添加一个文件夹动画到res文件夹。(名称必须是animator)。添加一个动画资源文件。例如res/animator/fade.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <objectAnimator
        android:propertyName="backgroundColor"
        android:duration="1000"
        android:valueFrom="#000000"
        android:valueTo="#FFFFFF"
        android:startOffset="0"
        android:repeatCount="-1"
        android:repeatMode="reverse" />
</set>

在Activity java文件中,调用这个

View v = getWindow().getDecorView().findViewById(android.R.id.content);
AnimatorSet set = (AnimatorSet) AnimatorInflater.loadAnimator(this, R.animator.fade);
set.setTarget(v);
set.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的另一个解决方案的答案,在这个答案最初发布时还不可用。

如果你想要这样的彩色动画,

这段代码将帮助你:

ValueAnimator anim = ValueAnimator.ofFloat(0, 1);   
anim.setDuration(2000);

float[] hsv;
int runColor;
int hue = 0;
hsv = new float[3]; // Transition color
hsv[1] = 1;
hsv[2] = 1;
anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {

    @Override
    public void onAnimationUpdate(ValueAnimator animation) {

        hsv[0] = 360 * animation.getAnimatedFraction();

        runColor = Color.HSVToColor(hsv);
        yourView.setBackgroundColor(runColor);
    }
});

anim.setRepeatCount(Animation.INFINITE);

anim.start();

基于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();
}

罗曼米诺克回答在kotlin和作为扩展函数

fun View.colorTransition(@ColorRes startColor: Int, @ColorRes endColor: Int, duration: Long = 250L){
    val colorFrom = ContextCompat.getColor(context, startColor)
    val colorTo =  ContextCompat.getColor(context, endColor)
    val colorAnimation: ValueAnimator = ValueAnimator.ofObject(ArgbEvaluator(), colorFrom, colorTo)
    colorAnimation.duration = duration

    colorAnimation.addUpdateListener {
        if (it.animatedValue is Int) {
            val color=it.animatedValue as Int
            setBackgroundColor(color)
        }
    }
    colorAnimation.start()
}

如果你想改变当前的背景色到新的颜色,那么你可以使用这个

fun View.colorTransition(@ColorRes endColor: Int, duration: Long = 250L){
    var colorFrom = Color.TRANSPARENT
    if (background is ColorDrawable)
        colorFrom = (background as ColorDrawable).color

    val colorTo =  ContextCompat.getcolor(context, endColor)
    val colorAnimation: ValueAnimator = ValueAnimator.ofObject(ArgbEvaluator(), colorFrom, colorTo)
    colorAnimation.duration = duration

    colorAnimation.addUpdateListener {
        if (it.animatedValue is Int) {
            val color=it.animatedValue as Int
            setBackgroundColor(color)
        }
    }
    colorAnimation.start()
}

使用

myView.colorTransition(R.color.bg_color)

你可以创建一个对象动画器。例如,我有一个targetView,我想改变你的背景颜色:

int colorFrom = Color.RED;
int colorTo = Color.GREEN;
int duration = 1000;
ObjectAnimator.ofObject(targetView, "backgroundColor", new ArgbEvaluator(), colorFrom, colorTo)
    .setDuration(duration)
    .start();