android:animation颜色从颜色变为颜色

假设我有两种颜色,我需要创build一个实时animation,从一种颜色快速切换到另一种颜色。

我试图增加颜色hex,直到我到达另一个,但这给了一个非常糟糕的animation,因为它显示了许多不相关的颜色。

我正在使用setColorFilter(color, colorfilter)来改变一个imageview的颜色。

改变色调会给我最好的视觉效果? 如果是这样,我怎样才能改变它一个纯色?

解决方法:我通过recursion移动色相来解决这个问题

 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); } 

Solutions Collecting From Web of "android:animation颜色从颜色变为颜色"

结合@ 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(); 

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

在这里输入图像说明

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

 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(); 

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

 ValueAnimator anim = ValueAnimator.ofArgb(color1, color2) 

您可以使用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(); 

在调用anim.start()之前,您还可以设置持续时间或其他参数。 例如:

 anim.setDuration(400); 

将animation持续时间设置为400ms。


最后,请注意, ValueAnimatorHoneycomb中可用,所以如果您支持较旧的SDK,则可以使用NineOldAndroids 。

其他的答案给了我一个奇怪的效果,当转换不同的颜色。 从黄色到灰色,在animation过程中的某个点会变成绿色。

最适合我的是以下代码片段。 这创造了一个真正平稳的过渡,没有奇怪的颜色出现在中间。

 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); } 

你可以使用TransitionDrawable

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

在drawable文件夹中创buildxml文件,你可以这样写:

 <transition xmlns:android="http://schemas.android.com/apk/res/android"> <item android:drawable="@drawable/end_color" /> <item android:drawable="@drawable/start_color" /> </transition> 

然后,在你的xml中,你可以在android:background属性中引用这个TransitionDrawable。

下面的代码片段对我来说是完美的。 我想使用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(); 

解决方法:我通过recursion移动色相来解决这个问题

 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); } 

在ColorUtils中使用blendARGB的最佳方法。

esay和最小的行代码。

 view.setBackgroundColor(ColorUtils.blendARGB(Color.parseColor("#FFFFFF"), Color.parseColor("#CCCCCC"), fraction)); 

首先,我要感谢@bcorso关于HSV的伟大答案和数据。

虽然我使用了一段时间的algorithm,但是我却对这个过程中颜色从一种颜色转换到另一种颜色的事实稍微感到有些恼火。 所以,我终于实现了我自己的愚蠢简单的algorithm,使用真正的3D坐标来做这样的插值:

https://github.com/konmik/animated-color

我试过@bcorso和@damienix,他们的解决scheme对我来说并不合适。 这个函数的math运算非常简单,因为它遵循基本的插值公式:

p(t)=(1-t)* p1 + t * p2,其中t [0,1]

 public int interpolateColorFromTo(int currColor, int nextColor, float t) { final float[] from = new float[3]; final float[] to = new float[3]; Color.colorToHSV(currColor, from); Color.colorToHSV(nextColor, to); final float[] hsv = new float[3]; hsv[0] = (1.0f - t) * from[0] + t * to[0]; hsv[1] = (1.0f - t) * from[1] + t * to[1]; hsv[2] = (1.0f - t) * from[2] + t * to[2]; return Color.HSVToColor(hsv); } 

我发现在Android源代码中ArgbEvaluator使用的实现在转换颜色方面做得最好。 在使用HSV时,根据两种颜色的不同,这个过渡对我来说是跳过太多的色彩。 但是这种方法没有。 如果您尝试简单地使用ArgbEvaluatoranimation使用ArgbEvaluatorValueAnimator

 ValueAnimator colorAnimation = ValueAnimator.ofObject(new ArgbEvaluator(), colorFrom, colorTo); colorAnimation.addUpdateListener(new AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animator) { view.setBackgroundColor((int) animator.getAnimatedValue()); } }); colorAnimation.start(); 

然而,如果你像我一样想要将你的转换与用户input的某个用户手势或其他值相关联,那么ValueAnimator的帮助不大(除非你的目标是API 22以上),在这种情况下,你可以使用ValueAnimator.setCurrentFraction()方法)。 在API 22下方定位时,将您在ArgbEvaluator源代码中find的代码封装在您自己的方法中,如下所示:

 public static int interpolateColor(float fraction, int startValue, int endValue) { int startA = (startValue >> 24) & 0xff; int startR = (startValue >> 16) & 0xff; int startG = (startValue >> 8) & 0xff; int startB = startValue & 0xff; int endA = (endValue >> 24) & 0xff; int endR = (endValue >> 16) & 0xff; int endG = (endValue >> 8) & 0xff; int endB = endValue & 0xff; return ((startA + (int) (fraction * (endA - startA))) << 24) | ((startR + (int) (fraction * (endR - startR))) << 16) | ((startG + (int) (fraction * (endG - startG))) << 8) | ((startB + (int) (fraction * (endB - startB)))); } 

并根据需要使用它。