2010-04-10 14 views
233

¿Cómo se anima el cambio del color de fondo de una vista en Android?Animar cambio de color de fondo en Android

Por ejemplo:

tengo una vista con un color de fondo rojo. El color de fondo de la vista cambia a azul. ¿Cómo puedo hacer una transición suave entre los colores?

Si esto no se puede hacer con vistas, una alternativa será bienvenida.

+9

Uno esperaría que una transición suave entre los colores no debería ser un problema para una plataforma como Android. Sin embargo, las vistas no están hechas para eso. La pregunta sigue en pie. – hpique

+0

Un buen [tutorial en video] (https://www.youtube.com/watch?v=bSgUn2rZiko) –

Respuesta

301

¡Terminé averiguando una (bastante buena) solución para este problema!

Puede usar un TransitionDrawable para lograr esto. Por ejemplo, en un archivo XML en la carpeta estirable podría escribir algo como:

<?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> 

Luego, en el código XML para la vista real que haría referencia a este TransitionDrawable en el atributo android:background.

En este punto se puede iniciar la transición en el código de mando haciendo:

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

O ejecutar la transición a la inversa, llamando al:

transition.reverseTransition(transitionTime); 

Ver Roman's answer de otra solución que utiliza la API de Property Animation, que no estaba disponible en el momento en que se publicó originalmente esta respuesta.

+1

Gracias mxrider! Esto responde la pregunta. Lamentablemente, no funciona para mí porque la vista que tiene TransitionDrawable como fondo tiene que ser animada también, y parece que la animación de vista anula la transición de fondo. ¿Algunas ideas? – hpique

+3

Lo resolvió iniciando el TransitionDrawable DESPUÉS de iniciar la animación. – hpique

+1

¡Impresionante! ¡Me alegra que lo hayas hecho funcionar! Hay muchas cosas interesantes que puedes hacer en xml con Android, muchas de las cuales están algo ocultas en los documentos y no son obvias en mi opinión. – idolize

9

Otra manera fácil de lograr esto es realizar un fundido usando AlphaAnimation.

  1. Haga su vista un ViewGroup
  2. Añadir un punto de vista del niño a ella en el índice 0, con dimensiones del diseño match_parent
  3. darle a su hijo el mismo fondo que el contenedor
  4. cambio a fondo del recipiente para el color de destino
  5. Atenúa al niño utilizando AlphaAnimation.
  6. retirar al niño cuando la animación es completa (usando un AnimationListener)
383

Puede utilizar las nuevas Property Animation Api para la animación de los colores:

int colorFrom = getResources().getColor(R.color.red); 
int colorTo = getResources().getColor(R.color.blue); 
ValueAnimator colorAnimation = ValueAnimator.ofObject(new ArgbEvaluator(), colorFrom, colorTo); 
colorAnimation.setDuration(250); // milliseconds 
colorAnimation.addUpdateListener(new AnimatorUpdateListener() { 

    @Override 
    public void onAnimationUpdate(ValueAnimator animator) { 
     textView.setBackgroundColor((int) animator.getAnimatedValue()); 
    } 

}); 
colorAnimation.start(); 

Por razones de compatibilidad con el uso de Android 2.x Nine Old Androids library de Jake Wharton.

El método getColor está desfasada y en Android M, por lo que tiene dos opciones:

  • Si utiliza la biblioteca de soporte, es necesario sustituir los getColor llamadas con:

    ContextCompat.getColor(this, R.color.red); 
    
  • Si no utiliza la biblioteca de soporte, debe reemplazar las llamadas getColor con:

    getColor(R.color.red); 
    
+2

solución "musthave" si está utilizando Property Animation API (o NineOldAndroid). Anima muy suavemente. –

+1

¿Hay alguna manera de establecer la duración de la transición de esta manera? – iGio90

+109

@ iGio90 sí, no lo vas a creer, pero el método llama a setDuration() :) –

110

Dependiendo de cómo obtiene su vista el color de fondo y cómo obtiene el color de destino hay varias formas diferentes de hacerlo.

Los dos primeros usan el marco Android Property Animation.

Utilice un Object Animator si:

  • Su punto de vista tiene su color de fondo define como un valor argb en un archivo XML.
  • Su vista ya han tenido establecer su color por view.setBackgroundColor()
  • Su punto de vista tiene su color de fondo se define en una estirable que no define propiedades adicionales como accidente cerebrovascular o radios de las esquinas.
  • Su vista tiene su color de fondo definido en un dibujo y desea eliminar cualquier propiedad adicional como trazo o radios de esquina, tenga en cuenta que la eliminación de las propiedades adicionales no se animará.

El objeto animador funciona llamando view.setBackgroundColor que sustituye al dibujable definido a menos que es una instancia de una ColorDrawable, que rara vez es. Esto significa que se eliminarán todas las propiedades de fondo adicionales de un trazo como trazos o esquinas.

Utilice un Value Animator si:

  • Su punto de vista tener su color de fondo se define en una estirable que también establece las propiedades como el golpe o esquina radios y desea cambiarlo a un nuevo color que se decidió durante la ejecución .

Utilice un Transition drawable si:

  • Su visión debe cambiar entre dos estirable que se han definido antes del despliegue.

he tenido algunos problemas de rendimiento con dibujables de transición que se ejecuta mientras yo estoy abriendo una DrawerLayout que no he sido capaz de resolver, por lo que si encuentra algún tartamudeo inesperada que podría haber topado con el mismo error que yo tener.

Deberá modificar el ejemplo de Value Animator si desea utilizar un StateLists drawable o un LayerLists drawable, de lo contrario, se bloqueará en la línea final GradientDrawable background = (GradientDrawable) view.getBackground();.

Object Animator:

Ver definición:

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

crear y utilizar un ObjectAnimator como este.

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

También puede cargar la definición de animación a partir de un XML usando un AnimatorInflater como XMight hace en Android objectAnimator animate backgroundColor of Layout

Value Animator:

Ver definición:

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

definición Disponibles:

<?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> 

crear y utilizar un ValueAnimator así:

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:

Ver definición:

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

definición Disponibles:

<?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> 

Uso del TransitionDrawable así:

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

puede invertir el animaciones llamando .reverse() en la instancia de animación.

Hay algunas otras maneras de hacer las animaciones, pero estos tres es probablemente el más común. Generalmente uso un ValueAnimator.

+0

Aquí hay un voto favorable para que pueda publicar enlaces. – gunr2171

+0

en realidad es posible definir y usar TransitionDrawable en el código, pero por alguna razón, no funciona la segunda vez. extraño. –

+0

Puedo usar el animador de objetos incluso cuando mi vista tiene establecido ColorDrawable. Simplemente lo guardo en una variable local, lo establezco en nulo y cuando la animación finaliza, vuelve a establecer el ColorDrawable original. –

3

Aquí es una función agradable que permite esto:

public static void animateBetweenColors(final View viewToAnimateItBackground, final int colorFrom, final int colorTo, 
     final int durationInMs) { 
    final ValueAnimator colorAnimation = ValueAnimator.ofObject(new ArgbEvaluator(), colorFrom, colorTo); 
    colorAnimation.addUpdateListener(new AnimatorUpdateListener() { 
     ColorDrawable colorDrawable = new ColorDrawable(colorFrom); 

     @Override 
     public void onAnimationUpdate(final ValueAnimator animator) { 
      colorDrawable.setColor((Integer) animator.getAnimatedValue()); 
      viewToAnimateItBackground.setBackgroundDrawable(colorDrawable); 
     } 
    }); 
    if (durationInMs >= 0) 
     colorAnimation.setDuration(durationInMs); 
    colorAnimation.start(); 
} 
+0

esto no es compatible con teléfonos de la versión de gama baja –

+1

@Kartheeks te refieres a Android 10 y por debajo? de ser así, puede usar fácilmente una biblioteca "nineOldAndroids" para sustentarlo: http://nineoldandroids.com/. la sintaxis es casi exactamente la misma. –

7

Este es el método que utilizo en una base de actividad para cambiar el fondo. Estoy usando GradientDrawables generado en código, pero podría adaptarse para adaptarse.

protected void setPageBackground(View root, int type){ 
     if (root!=null) { 
      Drawable currentBG = root.getBackground(); 
      //add your own logic here to determine the newBG 
      Drawable newBG = Utils.createGradientDrawable(type); 
      if (currentBG==null) { 
       if(Build.VERSION.SDK_INT<Build.VERSION_CODES.JELLY_BEAN){ 
        root.setBackgroundDrawable(newBG); 
       }else{ 
        root.setBackground(newBG); 
       } 
      }else{ 
       TransitionDrawable transitionDrawable = new TransitionDrawable(new Drawable[]{currentBG, newBG}); 
       transitionDrawable.setCrossFadeEnabled(true); 
       if(Build.VERSION.SDK_INT<Build.VERSION_CODES.JELLY_BEAN){ 
        root.setBackgroundDrawable(transitionDrawable); 
       }else{ 
        root.setBackground(transitionDrawable); 
       } 
       transitionDrawable.startTransition(400); 
      } 
     } 
    } 

actualización: En caso de que alguien se ejecuta en al mismo problema que he encontrado, por alguna razón en Android < 4.3 utilizando setCrossFadeEnabled(true) causa un efecto hacia fuera Blanco indeseable por lo que tuvo que cambiar a un color sólido para < 4.3 utilizando @Roman Minenok ValueAnimator método mencionado anteriormente.

+0

Esto es exactamente lo que estaba buscando. ¡Gracias! :) – cyph3r

37

Usted puede hacer un animador objeto.Por ejemplo, tengo un TargetView y quiero cambiar el color de fondo:

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

Gracias. Love new API – ruX

+0

Desde API 21, puede usar 'ofArgb (targetView," backgroundColor ", colorFrom, colorTo)'. Su implementación es simplemente 'ofInt (...). SetEvaluator (nuevo ArgbEvaluator())'. – ypresto

14

Si desea animación de color de este tipo,

Enter image description here

este código le ayudará a:

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

¿Dónde está la parte cuando se inicializa la variable ** anim **? – VoW

1

He encontrado que la implementación utilizada por ArgbEvaluator en el código fuente de Android funciona mejor en la transición de colores. Cuando usé HSV, dependiendo de los dos colores, la transición saltó demasiados matices para mí. Pero este método no.

Si usted está intentando simplemente animar, utilice ArgbEvaluator con ValueAnimator como se sugiere here:

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 quieren atar su transición con algún gesto de usuario u otro valor que se pasa de una de entrada, el ValueAnimator no es de mucha ayuda (a menos que tenga como objetivo la API 22 y superior, en cuyo caso puede usar el método ValueAnimator.setCurrentFraction()). Cuando el objetivo es continuación de la API 22, envolver el código que se encuentra en ArgbEvaluator source code en su propio método, tal 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 usarlo como desee.

1

mejor uso manera ValueAnimator y 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(); 
1

respuesta se da de muchas maneras. También puede usar ofArgb(startColor,endColor) de ValueAnimator.

de 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(); 
Cuestiones relacionadas