Animate change of view background color on Android

2018-12-31 17:13发布

How do you animate the change of background color of a view on Android?

For example:

I have a view with a red background color. The background color of the view changes to blue. How can I do a smooth transition between colors?

If this can't be done with views, an alternative will be welcome.

12条回答
笑指拈花
2楼-- · 2018-12-31 17:29

Depending on how your view gets its background color and how you get your target color there are several different ways to do this.

The first two uses the Android Property Animation framework.

Use a Object Animator if:

  • Your view have its background color defined as a argb value in a xml file.
  • Your view have previously had its color set by view.setBackgroundColor()
  • Your view have its background color defined in a drawable that DOES NOT defines any extra properties like stroke or corner radiuses.
  • Your view have its background color defined in a drawable and you want to remove any extra properties like stroke or corner radiuses, keep in mind that the removal of the extra properties will not animated.

The object animator works by calling view.setBackgroundColor which replaces the defined drawable unless is it an instance of a ColorDrawable, which it rarely is. This means that any extra background properties from a drawable like stroke or corners will be removed.

Use a Value Animator if:

  • Your view have its background color defined in a drawable that also sets properties like the stroke or corner radiuses AND you want to change it to a new color that is decided while running.

Use a Transition drawable if:

  • Your view should switch between two drawable that have been defined before deployment.

I have had some performance issues with Transition drawables that runs while I am opening a DrawerLayout that I haven't been able to solve, so if you encounter any unexpected stuttering you might have run into the same bug as I have.

You will have to modify the Value Animator example if you want to use a StateLists drawable or a LayerLists drawable, otherwise it will crash on the final GradientDrawable background = (GradientDrawable) view.getBackground(); line.

Object Animator:

View definition:

<View
    android:background="#FFFF0000"
    android:layout_width="50dp"
    android:layout_height="50dp"/>

Create and use a ObjectAnimator like this.

final ObjectAnimator backgroundColorAnimator = ObjectAnimator.ofObject(view,
                                                                       "backgroundColor",
                                                                       new ArgbEvaluator(),
                                                                       0xFFFFFFFF,
                                                                       0xff78c5f9);
backgroundColorAnimator.setDuration(300);
backgroundColorAnimator.start();

You can also load the animation definition from a xml using a AnimatorInflater like XMight does in Android objectAnimator animate backgroundColor of Layout

Value Animator:

View definition:

<View
    android:background="@drawable/example"
    android:layout_width="50dp"
    android:layout_height="50dp"/>

Drawable definition:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <solid android:color="#FFFFFF"/>
    <stroke
        android:color="#edf0f6"
        android:width="1dp"/>
    <corners android:radius="3dp"/>

</shape>

Create and use a ValueAnimator like this:

final ValueAnimator valueAnimator = ValueAnimator.ofObject(new ArgbEvaluator(),
                                                           0xFFFFFFFF,
                                                           0xff78c5f9);

final GradientDrawable background = (GradientDrawable) view.getBackground();
currentAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {

    @Override
    public void onAnimationUpdate(final ValueAnimator animator) {
        background.setColor((Integer) animator.getAnimatedValue());
    }

});
currentAnimation.setDuration(300);
currentAnimation.start();

Transition drawable:

View definition:

<View
    android:background="@drawable/example"
    android:layout_width="50dp"
    android:layout_height="50dp"/>

Drawable definition:

<?xml version="1.0" encoding="utf-8"?>
<transition xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <shape>
            <solid android:color="#FFFFFF"/>
            <stroke
                android:color="#edf0f6"
                android:width="1dp"/>
            <corners android:radius="3dp"/>
        </shape>
    </item>

    <item>
        <shape>
            <solid android:color="#78c5f9"/>
            <stroke
                android:color="#68aff4"
                android:width="1dp"/>
            <corners android:radius="3dp"/>
        </shape>
    </item>
</transition>

Use the TransitionDrawable like this:

final TransitionDrawable background = (TransitionDrawable) view.getBackground();
background.startTransition(300);

You can reverse the animations by calling .reverse() on the animation instance.

There are some other ways to do animations but these three is probably the most common. I generally use a ValueAnimator.

查看更多
大哥的爱人
3楼-- · 2018-12-31 17:29

Another easy way to achieve this is to perform a fade using AlphaAnimation.

  1. Make your view a ViewGroup
  2. Add a child view to it at index 0, with match_parent layout dimensions
  3. Give your child the same background as the container
  4. Change to background of the container to the target color
  5. Fade out the child using AlphaAnimation.
  6. Remove the child when the animation is complete (using an AnimationListener)
查看更多
梦该遗忘
4楼-- · 2018-12-31 17:33

best way is to use ValueAnimator and ColorUtils.blendARGB

 ValueAnimator valueAnimator = ValueAnimator.ofFloat(0.0f, 1.0f);
 valueAnimator.setDuration(325);
 valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator valueAnimator) {

              float fractionAnim = (float) valueAnimator.getAnimatedValue();

              view.setColorBackground(ColorUtils.blendARGB(Color.parseColor("#FFFFFF")
                                    , Color.parseColor("#000000")
                                    , fractionAnim));
        }
});
valueAnimator.start();
查看更多
只若初见
5楼-- · 2018-12-31 17:37

Answer is given in many ways. You can also use ofArgb(startColor,endColor) of ValueAnimator.

for API > 21:

int cyanColorBg = ContextCompat.getColor(this,R.color.cyan_bg);
int purpleColorBg = ContextCompat.getColor(this,R.color.purple_bg);

ValueAnimator valueAnimator = ValueAnimator.ofArgb(cyanColorBg,purpleColorBg);
        valueAnimator.setDuration(500);
        valueAnimator.setInterpolator(new LinearInterpolator());
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
              @Override
              public void onAnimationUpdate(ValueAnimator valueAnimator) {
                   relativeLayout.setBackgroundColor((Integer)valueAnimator.getAnimatedValue());
              }
        });
        valueAnimator.start();
查看更多
流年柔荑漫光年
6楼-- · 2018-12-31 17:41

You can make an object animator. For example, I have a targetView and I want to change your background color:

int colorFrom = Color.RED;
int colorTo = Color.GREEN;
int duration = 1000;
ObjectAnimator.ofObject(targetView, "backgroundColor", new ArgbEvaluator(), colorFrom, colorTo)
    .setDuration(duration)
    .start();
查看更多
皆成旧梦
7楼-- · 2018-12-31 17:41

If you want color animation like this,

Enter image description here

this code will help you:

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();
查看更多
登录 后发表回答