lunes, 9 de junio de 2014

Android: animaciones de objetos utilizando "Property Animation"


Hola a todos de nuevo. Ahora os enseñaré como utilizar las animaciones sobre los objetos de nuestros layout's y activity's para que giren, se desplacen y aparezcan y oculten. Sin duda, le dará un toque más refinado a nuestras aplicaciones.

Pues bien, nos centraremos en ver como realizar:
- desplazamientos (eje horizontal y vertical)
- rotaciones
- desvanecimientos (parámetro "alpha")
- animaciones en el cambio de color



Antes de comenzar os voy a pasar este tutorial que encontré, y del cual quiero hacer eco porque está muy bien redactado y explicado. Si lo seguís realizaréis un pequeño ejemplo de todo esto que os he nombrado antes y veréis que resulta muy "simple".

El tutorial está en inglés, y la mayoría de animaciones las realiza utilizando Java + XML. Personalmente no me gusta mucho el estilo de XML pues pienso que te restringe un poco las cosas y si vamos a realizar cambios y modificaciones de forma dinámica, mejor hacerlo directamente vía código para evitar repetirnos. 

Aunque hay algunas cosas como las geometrías del suelo o del sol que viene muy bien definir en el XML y simplemente cargarlas después.


Antes de comenzar tenemos que crearnos una nueva carpeta que cuelgue del directorio "res", y que llamaremos "animator". Será aquí donde iremos guardando las animaciones que queramos hacer en XML. Las geometrías las guardaremos en la carpeta "drawable" (si no la tenemos, la creamos igualmente).

Pues bien, la primera animación que veremos será la del Sol. Aquí he utilizado los mismo que en el tutorial anterior: un XML para definir nuestra geometría y código en Java para controlarlo.

1) Animación del Sol: desplazamiento en el eje X (horizontal)

Empezamos definiéndonos la geometría del Sol: sun.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:dither="true"
    android:shape="oval" >
    
    <gradient
        android:endColor="#ffff6600"
        android:gradientRadius="150"
        android:startColor="#ffffcc00"
        android:type="radial"
        android:useLevel="false" />
    
    <size
        android:height="100dp"
        android:width="100dp" />


</shape>

A continuación nos definimos también en XML la animación del Sol, que en este caso realizará un desplazamiento en el eje X: sun_moving.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:interpolator="@android:anim/accelerate_decelerate_interpolator"
    android:ordering="sequentially" >
    
    <objectAnimator
        android:duration="3000"
        android:propertyName="x"
        android:repeatCount="infinite"
        android:repeatMode="reverse"
        android:valueTo="-400"
        android:valueType="floatType"
         />    


</set>

El "valueTo" es el valor hacia el que tiene que llegar. Como no se especifica el "valueFrom", se toma por defecto el 0, que viene a ser el inicio.

Acto seguido pasamos al código de nuestra Activity donde controlaremos la animación.
Antes de eso, en nuestro layout tenemos que colocar la geometría. Yo la he colocado usando un ImageView de la forma siguiente (activity_main.xml):

    <ImageView
   android:id="@+id/sun"
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   android:contentDescription="The Sun"
   android:paddingLeft="100dp"
   android:paddingTop="45dp"

   android:src="@drawable/sun" />


Hecho esto, pasamos al código de la Activity.
Hacemos como siempre, nos creamos una variable que reconozca el ImageView del Sol y a su vez, una variable del tipo "AnimatorSet".

Esta variable es un conjunto cuyo objetivo es el de contener muchas animaciones aplicadas a un mismo objeto o a diferentes objetos. Su uso resulta bastante sencillo y yo aconsejo usarlo si pretendemos hacer animaciones algo más complejas (ya sea para un mismo objeto como para varios).

Además tiene la gran ventaja de que nos permite establecer "coreografías", esto es, decidir si queremos que las animaciones que contiene se ejecuten en un determinado orden, todas a la vez, etc. etc.

El código es el siguiente:

// reconocemos el image view
sun = (ImageView) this.findViewById(R.id.sun);
// inflamos el XML de la animación
sunSet = (AnimatorSet) AnimatorInflater.loadAnimator(this, R.animator.sun_moving);
// seleccionamos el objetivo de la animación inflada
sunSet.setTarget(sun);
// ejecutamos la animación con el objetivo ya establecido

sunSet.start();

Y con esto ya tenemos nuestro Sol en movimiento.


2) Rotaciones

Ahora os mostraré cómo se realiza una rotación vía código (sin nada de XML).

Lo primero es reconocer al objeto de nuestro layout al que animaremos y crearnos nuestra variable global privada del tipo "AnimatorSet" para controlar las animaciones que hagamos. En mi caso, yo controlaré un ImageView con una foto de un pez, así que mis variables serán:

private ImageView fish ;
private AnimatorSet fishSet ;

...

// dentro del método onCreate....

fish = (ImageView) this.findViewById(R.id.fish);
fishSet = new AnimatorSet();
// nos declaramos un interpolador de keyframes. Hay varios tipos de interpoladores muy
// interesantes, y os animo a que los descubráis y probéis. Yo utilizo un interpolador
// linear porque es el más básico y simple que hay, y para un tutorial viene perfecto.
TimeInterpolator inter = new LinearInterpolator();

// Esta variable será la animación a representar. 
// Como parámetros le pasamos: el objeto objetivo, el tipo de propiedad a animar (en este
// caso, la propiedad de rotación), los grados desde los que empieza (360), hasta los grados
// finales.
// Dependiendo de cuál sea mayor, giraremos horaria o antihorariamente.
ValueAnimator rotateFish = ObjectAnimator.ofFloat(fish, "rotation", 360, 0);
rotateFish.setDuration(3000)
 .setRepeatCount(ValueAnimator.INFINITE); // animación infinita
rotateFish.setInterpolator(inter); // establecemos el interpolador

// Añadimos la animación dentro del AnimatorSet
fishSet.play( rotateFish );
// Ejecutamos el set y por ende, nuestra animación
fishSet.start();

Con esto ya podremos ver al objeto que hayamos escogido rotar sobre sí mismo de forma infinita.

Como dato adicional, si lo que queremos es realizar una animación un poco más compleja haciendo que a la vez que rota sobre sí, se desplaza horizontalmente, tenemos que crear la animación que realice el desplazamiento aplicado sobre el objeto y añadirlo al AnimatorSet de forma especial:

// Esta es la animación que se encarga del desplazamiento
ValueAnimator moveFish = ObjectAnimator.ofFloat(fish, "x", 300);
moveFish.setDuration(3000)
.setRepeatMode(ValueAnimator.REVERSE); // al llegar al final, volverá al inicio
moveFish.setRepeatCount(ValueAnimator.INFINITE); 
moveFish.setInterpolator(inter);

// sustituimos la línea "fishSet.play(...)" anterior por esta...
fishSet.playTogether( rotateFish, moveFish ); // se ejecutarán a la vez

Otra opción sería la de hacer una coreografía en la que primero se ejecute el desplazamiento y cuando haya acabado, que se ejecute la rotación. Esto se consigue añadiendo ambas animaciones de esta forma al AnimatorSet:

fishSet.play( moveFish ).before( rotateFish );

Lo que le decimos con la línea anterior es que ejecute la animación "moveFish" antes que la animación "rotateFish".


3) Desvanecimientos (parámetro alpha)

Los desvanecimientos son un efecto que modifica el parámetro "alpha" de todos los objetos. Dicho parámetro controla la transparencia del objeto y su valor se mueve entre 0 (invisible) y 1 (visible).

Para crear y usar una animación que haga que se desvanezca un objeto, o haga que aparezca de la nada tenemos que crear la animación como hemos visto anteriormente, añadirla al AnimatorSet y ejecutarla.

Se crea de esta forma:

// comenzamos con el objeto visible y lo vamos haciendo invisible
ValueAnimator fadeAnim = ObjectAnimator.ofFloat(fish, "alpha", 1f, 0f);
fadeAnim.setDuration(3000);
fadeAnim.setRepeatCount(ValueAnimator.INFINITE);
fadeAnim.setRepeatMode(ValueAnimator.REVERSE);

Después lo añadimos y ejecutamos como ya hemos visto anteriormente.


4) Animación de Cambio de Color

Esta sin duda, es una de mis animaciones favoritas. De esta forma, podemos llegar a recrear el paso del día a la noche en nuestra activity.

Como primer paso, al layout de nuestra activity le daremos un color de fondo añadiendo la siguiente línea al XML:

android:background="#66ccff"

Ahora si volvemos al código de la activity, tenemos que escribir lo siguiente:

// animación: de un color a otro color
ValueAnimator skyAnim = ObjectAnimator.ofInt( findViewById(R.id.fifth_activity_sky), "backgroundColor", Color.rgb(0x66, 0xcc, 0xff)Color.rgb(0x00, 0x66, 0x99));
skyAnim.setDuration(3000);
skyAnim.setRepeatCount(ValueAnimator.INFINITE);
skyAnim.setRepeatMode(ValueAnimator.REVERSE);
skyAnim.setEvaluator(new ArgbEvaluator()); // parecido al interpolador en cuanto a función
skyAnim.start();

En este trozo de código tenemos que el objeto sobre el que actuamos es el propio layout al que le hemos puesto un id: R.id.fifth_activity_sky.

Y como nota, en este trozo de código no ha hecho falta la utilización de un "AnimatorSet". Nos ha bastado con la propia animación.




Y eso es todo lo que puedo enseñaros por ahora sobre este tipo de animaciones. Espero que os haya gustado y os animéis a hacer algo relacionado con esto.

Aquí os dejo un link con más información al respecto.

Hasta otra!!

No hay comentarios:

Publicar un comentario