Join FlipAndroid.COM Telegram Group: https://t.me/joinchat/F_aqThGkhwcLzmI49vKAiw


Android: Animar el cambio de color de color a color

Suponiendo que tengo dos colores, y tengo que crear una animación en tiempo real que cambia rápidamente de un color a otro.

Intenté incrementar el color hexadecimal hasta llegar al otro, pero eso dio una muy mala animación ya que mostraba muchos colores no relacionados.

Estoy utilizando setColorFilter(color, colorfilter) para cambiar el color de una imagen.

Cambiar el HUE me dará los mejores resultados visuales? Si es así, ¿cómo puedo cambiarlo por un color sólido?

SOLUCIÓN: Lo resolví cambiando el tono de forma recursiva

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

  • Encontrar el color dominante de una imagen en un @drawable de Android
  • Error al analizar los colores de la cadena
  • Cómo tintar un mapa de bits a un color sólido
  • Color negro androide a 85% de opacidad
  • Establecer dinámicamente el color del tema
  • ¿Cuál es el color predeterminado para el texto en textview?
  • Android: cambia el texto del botón y el color de fondo
  • Cómo cambiar el color de la pista de un SwitchCompat
  • 10 Solutions collect form web for “Android: Animar el cambio de color de color a color”

    La combinación de la respuesta de @ zed y @ Phil le da una buena transición suave usando el 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(); 

    El HSV dará una transición más agradable que el espacio de color por defecto de Androids porque HSV describe colores en coordenadas cilíndricas que separan bien las propiedades del color y permiten una transición suave a través de un solo eje. Usted puede ver a partir de la imagen de abajo que viajar a lo largo de las direcciones H, S o V da una buena transición continua entre los colores.

    Introduzca aquí la descripción de la imagen

    Simplemente puede usar ArgbEvaluator que está disponible desde 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(); 

    Aún mejor, a partir de la API 21 (Lollipop 5.0) puede reemplazar las primeras 3 líneas del código anterior por una:

     ValueAnimator anim = ValueAnimator.ofArgb(color1, color2) 

    Puede utilizar un 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(); 

    También puede establecer la duración u otros parámetros antes de llamar a anim.start() . Por ejemplo:

     anim.setDuration(400); 

    Establecerá la duración de la animación a 400 ms.


    Por último, tenga en cuenta que ValueAnimator está disponible a partir de Honeycomb , por lo que si está apoyando más antiguos SDK, puede utilizar NineOldAndroids .

    Las otras respuestas me dieron un efecto extraño cuando la transición de colores muy diferentes. De amarillo a gris, llegaría a verde en algún momento durante la animación.

    Lo que mejor funcionó para mí fue el siguiente fragmento. Esto creó una transición realmente suave sin ningún tipo de colores extraños apareciendo en el medio.

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

    Puede utilizar TransitionDrawable

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

    Crear archivo xml en la carpeta dibujable que podría escribir algo como:

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

    A continuación, en su xml para la vista actual, haría referencia a este TransitionDrawable en el atributo android: background.

    El fragmento siguiente funcionó perfectamente para mí. Pensé en usar ValueAnimator.ofArgb (), pero que requiere un mínimo de api 21. En lugar de lo siguiente funciona con api 11 y superior. Logra el cambio de color suavemente.

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

    SOLUCIÓN: Lo resolví cambiando el tono de forma recursiva

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

    En primer lugar, me gustaría agradecer a @bcorso por la gran respuesta y datos sobre HSV.

    Mientras estaba usando el algoritmo propuesto durante algún tiempo, me sentí un poco molesto por el hecho de que hace un cambio de color de un color a otro tocar los colores no relacionados en el proceso. Por lo tanto, finalmente implementó mi propio estúpido algoritmo simple que utiliza coordenadas reales 3D para hacer tal interpolación:

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

    He intentado @corazón y @damienix y su solución no funcionó para mí. La matemática en esta función es mucho más simple, ya que sigue la fórmula de interpolación básica:

    P (t) = (1 – t) * p1 + t * p2, donde 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); } 

    He descubierto que la implementación utilizada por ArgbEvaluator en el código fuente android hace mejor trabajo en la transición de colores. Cuando se utiliza HSV, dependiendo de los dos colores, la transición fue saltar a través de demasiados matices para mí. Pero este método no lo hace. Si está intentando simplemente animar, utilice ArgbEvaluator con ValueAnimator como se sugiere aquí :

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

    Sin embargo, si usted es como yo y quiere atar su transición con algún gesto del usuario u otro valor pasado de una entrada, el ValueAnimator no es de mucha ayuda (a menos que usted está apuntando para API 22 y arriba, en cuyo caso usted puede utilizar el ValueAnimator.setCurrentFraction() ). Al orientar por debajo de la API 22, envuelva el código encontrado en el código fuente de ArgbEvaluator en su propio método, como se muestra a continuación:

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

    Y úsalo como quieras.

    FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.