android:动画颜色从颜色变为颜色

zed*_*zed 46 android colors

假设我有两种颜色,我需要创建一个快速从颜色切换到另一种颜色的实时动画.

我试图增加十六进制的颜色,直到我到达另一个,但这给了一个非常糟糕的动画,因为它显示了许多不相关的颜色.

setColorFilter(color, colorfilter)用来改变imageview的颜色.

改变HUE会给我最好的视觉效果吗?如果是这样,我怎样才能将其改为纯色?

解决方案:我通过递归移位色调来解决它

private int hueChange(int c,int deg){
       float[] hsv = new float[3];       //array to store HSV values
       Color.colorToHSV(c,hsv); //get original HSV values of pixel
       hsv[0]=hsv[0]+deg;                //add the shift to the HUE of HSV array
       hsv[0]=hsv[0]%360;                //confines hue to values:[0,360]
       return Color.HSVToColor(Color.alpha(c),hsv);
    }
Run Code Online (Sandbox Code Playgroud)

bco*_*rso 74

结合@ zed和@ Phil的答案,可以使用ValueAnimator.

final float[] from = new float[3],
              to =   new float[3];

Color.colorToHSV(Color.parseColor("#FFFFFFFF"), from);   // from white
Color.colorToHSV(Color.parseColor("#FFFF0000"), to);     // to red

ValueAnimator anim = ValueAnimator.ofFloat(0, 1);   // animate from 0 to 1
anim.setDuration(300);                              // for 300 ms

final float[] hsv  = new float[3];                  // transition color
anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener(){
    @Override public void onAnimationUpdate(ValueAnimator animation) {
        // Transition along each axis of HSV (hue, saturation, value)
        hsv[0] = from[0] + (to[0] - from[0])*animation.getAnimatedFraction();
        hsv[1] = from[1] + (to[1] - from[1])*animation.getAnimatedFraction();
        hsv[2] = from[2] + (to[2] - from[2])*animation.getAnimatedFraction();

        view.setBackgroundColor(Color.HSVToColor(hsv));
    }
});

anim.start();                                        
Run Code Online (Sandbox Code Playgroud)

HSV将提供比Androids默认色彩空间更好的过渡,因为HSV描述了圆柱坐标中的颜色,可以很好地分离颜色的属性并允许在单个轴上平滑过渡.您可以从下图中看到,沿着H,S或V方向行进可以在颜色之间进行良好的连续过渡.

在此输入图像描述

  • 这实际上看起来很糟糕,因为例如从蓝色到深灰色的动画会穿过绿色、黄色甚至一些红色。 (2认同)

dim*_*suz 53

您可以简单地使用ArgbEvaluator自API 11(Honeycomb)以来可用的内容:

ValueAnimator anim = new ValueAnimator();
anim.setIntValues(color1, color2);
anim.setEvaluator(new ArgbEvaluator());
anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator valueAnimator) {
        view.setBackgroundColor((Integer)valueAnimator.getAnimatedValue());
    }
});

anim.setDuration(300);
anim.start();
Run Code Online (Sandbox Code Playgroud)

更好的是,从API 21(Lollipop 5.0)开始,您可以将上面代码中的前3行替换为:

ValueAnimator anim = ValueAnimator.ofArgb(color1, color2)
Run Code Online (Sandbox Code Playgroud)

  • @knutella 我需要在 `setIntValues(...)` 之后调用 `setEvaluator(...)` 以防止闪烁。 (2认同)

Phi*_*hil 20

你可以使用ValueAnimator:

//animate from your current color to red
ValueAnimator anim = ValueAnimator.ofInt(view.getBackgroundColor(), Color.parseColor("#FF0000"));
anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator animation) {
        view.setBackgroundColor(animation.getAnimatedValue());
    }
});

anim.start();
Run Code Online (Sandbox Code Playgroud)

您还可以在呼叫前设置持续时间或其他参数anim.start().例如:

anim.setDuration(400);
Run Code Online (Sandbox Code Playgroud)

将动画持续时间设置为400毫秒.


最后,请注意ValueAnimatorHoneycomb开始可用,因此如果您支持较旧的SDK,则可以使用NineOldAndroids.

  • @ ZaidDaba'een从我的经验来看,这确实提供了非常具有视觉吸引力的效果,但是我很高兴你找到了适合你的其他东西. (4认同)
  • 如果没有ARGB评估(如下所述),这将只是迭代颜色整数,在大多数情况下看起来会很糟糕. (3认同)

Fer*_*ari 11

在转换非常不同的颜色时,其他答案给了我一个奇怪的效果.从黄色到灰色,它会在动画期间的某个时刻达到绿色.

对我来说最有效的是以下片段.这创造了一个非常平滑的过渡,中间没有出现奇怪的颜色.

private void changeViewColor(View view) {
    // Load initial and final colors.
    final int initialColor = getResources().getColor(R.color.some_color);
    final int finalColor = getResources().getColor(R.color.another_color);

    ValueAnimator anim = ValueAnimator.ofFloat(0, 1);
    anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            // Use animation position to blend colors.
            float position = animation.getAnimatedFraction();
            int blended = blendColors(initialColor, finalColor, position);

            // Apply blended color to the view.
            view.setBackgroundColor(blended);
        }
    });

    anim.setDuration(500).start();
}

private int blendColors(int from, int to, float ratio) {
    final float inverseRatio = 1f - ratio;

    final float r = Color.red(to) * ratio + Color.red(from) * inverseRatio;
    final float g = Color.green(to) * ratio + Color.green(from) * inverseRatio;
    final float b = Color.blue(to) * ratio + Color.blue(from) * inverseRatio;

    return Color.rgb((int) r, (int) g, (int) b);
}
Run Code Online (Sandbox Code Playgroud)


Muh*_*Ali 8

您可以使用TransitionDrawable

TransitionDrawable transition = (TransitionDrawable) viewObj.getBackground();
transition.startTransition(transitionTime);
Run Code Online (Sandbox Code Playgroud)

在drawable文件夹中创建xml文件,您可以编写如下内容:

<transition xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/end_color" />
    <item android:drawable="@drawable/start_color" />
</transition>
Run Code Online (Sandbox Code Playgroud)

然后,在实际View的xml中,您将在android:background属性中引用此TransitionDrawable.


Ras*_*iri 7

最好的方法是在ColorUtils中使用blendARGB。

esay和最小行代码。

view.setBackgroundColor(ColorUtils.blendARGB(Color.parseColor("#FFFFFF"), Color.parseColor("#CCCCCC"), fraction));
Run Code Online (Sandbox Code Playgroud)


pat*_*elb 5

以下代码片段非常适合我。我想过使用 ValueAnimator.ofArgb() 但这至少需要 api 21。相反,以下适用于 api 11 及更高版本。它实现了平滑的颜色变化。

ArgbEvaluator evaluator = new ArgbEvaluator();
ValueAnimator animator = new ValueAnimator();
animator.setIntValues(Color.parseColor("#FFFFFF"), Color.parseColor("#000000"));
animator.setEvaluator(evaluator);
animator.setDuration(1000);
//animator.setRepeatCount(ValueAnimator.INFINITE);
//animator.setRepeatMode(ValueAnimator.REVERSE);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            color = (int) animation.getAnimatedValue();
            //postInvalidate(); if you are animating a canvas
            //View.setBackgroundColor(color); another exampleof where to use
        }
    });
animator.start();
Run Code Online (Sandbox Code Playgroud)


zed*_*zed 3

解决方案:我通过递归改变色调解决了这个问题

private int hueChange(int c,int deg){
       float[] hsv = new float[3];       //array to store HSV values
       Color.colorToHSV(c,hsv); //get original HSV values of pixel
       hsv[0]=hsv[0]+deg;                //add the shift to the HUE of HSV array
       hsv[0]=hsv[0]%360;                //confines hue to values:[0,360]
       return Color.HSVToColor(Color.alpha(c),hsv);
    }
Run Code Online (Sandbox Code Playgroud)

  • 对于此类事情,您应该使用“ValueAnimator”。我已经发布了关于如何使用 HSV 值执行此操作的答案。 (2认同)