Androideity

Programación android en español, tutoriales, documentación, noticias, smartphones, tablets, programación android, aplicaciones android

Animaciones en Android I: Frame by Frame

| | 33 Comentarios

En un post anterior, vimos cómo utilizar animaciones en un contenedor llamado ViewFlipper. Esta es una de las tantas opciones que existen para poder trabajar con animaciones y el día de hoy vamos a conocer otras alternativas disponibles para darle ese look & feel que estás buscando a tus aplicaciones.

En Android podemos utilizar tres tipos de animaciones:

  • Animaciones Frame-by-frame

Una serie de frames que se “ejecutan” uno tras otros a intervalos de tiempos específicos.

  • Animaciones de layouts

Animaciones sobre las vistas de un contenedor tales como listas y tablas.

  • Animaciones de vistas

Animaciones sobre los contenedores (como el ViewFlipper visto anteriormente).

Los dos últimos tipos nos ayudan a insertar las animaciones adecuadas en base a la idea de su estado inicial y final que depende de las acciones que realice el usuario dentro de la aplicación, pudiendo así modificar el tamaño, color, posición, entre otros atributos de los widgets de la pantalla.

Animaciones Frame-by-frame

El día de hoy vamos a hacer un ejemplo de cómo se trabaja con este primer tipo de animación.

1. Creamos un nuevo proyecto llamado AnimacionFrame con la versión 2.2 de Android.

2. Elegimos 10 imágenes, de preferencia procura que sean del mismo tamaño y si puedes conseguir imágenes que tengan una secuencia mejor. En mi caso serán 10 imágenes de Android que te puedes descargar desde aquí.

3. Estas imágenes deberás pegarlas dentro del directorio res > drawable de tu proyecto.

4. Pasemos ahora a definir el layout de la aplicación. Esto lo haremos modificando el archivo main.xml del directorio res > layout de nuestro proyecto. A continuación te comparto el código que deberás escribir en este archivo:

Hemos definido un TextView para desplegar un mensaje al usuario, un Button que nos servirá para iniciar la animación y un ImageView que nos ayudará a crear la animación.

En Android, logramos crear animaciones frame by frame utilizando la clase AnimationDrawable, que toma una lista de recursos de tipo Drawable como lo son las imágenes y presentarlas una a una en intervalos de tiempo definidos. Podemos pensar en esta clase como un contenedor de recursos para crear animaciones y a través de cuál podemos hacer uso de los atributos de la clase Drawable.

5. Las animaciones también son recursos de nuestra aplicación, y en este caso es necesario crear un archivo XML en el directorio res > drawable. Damos clic derecho New > Other > Android XML File y definimos los siguientes parámetros:

6. En este archivo vamos a indicar qué recursos de imágenes utilizará nuestra animación. A continuación te muestro cómo deberá quedarte el archivo frame_animation.xml (o como se llame tu archivo):

7. Ahora pasemos a la actividad principal del proyecto. Escribimos las sentencias import que necesitaremos:

import android.app.Activity;
import android.graphics.drawable.AnimationDrawable;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;

8. Creamos un método llamado animate() que es el que hará la magia que buscamos en nuestra aplicación:

private void animate(){
    	ImageView imgView = (ImageView)findViewById(R.id.imagen);
    	imgView.setVisibility(ImageView.VISIBLE);
    	imgView.setBackgroundResource(R.drawable.frame_animation);

    	AnimationDrawable frame = (AnimationDrawable) imgView.getBackground();
    	if(frame.isRunning()){
    		frame.stop();
    	}else{
    		frame.stop();
    		frame.start();
    	}
    }

En este método recuperamos la ImageView que declaramos en el archivo main.xml y le asignamos el recurso de animación que creamos en el archivo frame_animation.xml del directorio res > drawable. Después a través de un parse sencillo creamos e inicializamos un objeto de tipo AnimationDrawable. La condición nos servirá para detener e iniciar la animación cuando nosotros queramos.

9. Por último, únicamente nos hace falta recuperar la referencia del botón que iniciará la animación a través de su evento onClick() que escribiremos dentro del método onCreate() de la actividad:

Button btn_start = (Button)findViewById(R.id.btn_start);
        btn_start.setOnClickListener(new OnClickListener(){
        	public void onClick(View v){
        		animate();
        	}
        });

10. Ejecutamos la aplicación y veremos como baila nuestro Android.

En el siguiente post veremos cómo animar cada uno de los widgets que agreguemos a nuestros layouts. ¡No te lo pierdas!

Descárgate el código fuente de este tutorial:

Referencia | Bogotobogo

¿Te gustó este post? ¡Compártelo!

 

Comparte este post

Acerca de: Condesa

Desarrolladora de aplicaciones Android, freelance, apasionada de la tecnología, y precursora del crecimiento tecnológico en México.

Sígueme en Twitter

Leer todos mis artículos

También puede interesarte

Comentarios de este artículo

  • Walter Barreto Salas

    Hola condesa , vi en otro tutorial que creastes una base de datos usando sqlite , me parecio vacan , segui lo mismos pasos y me ejecuto bien , ahora mi preguntas es como puedo crear un buscador usando AutocompleteTextViews , que cuando haga una busqueda sobre algun contacto que añadi a mi base de datos , me ayude el AutocompleteTextViews , sugeriendo los nombres que quiero buscar , como lo puedo hacer condesa ?

    • Anonymous

      Es realmente muy sencillo y si no mal recuerdo existe un ejemplo en la web de StackOverflow, te sugiero que busques ahí para ver el ejemplo :) saludos!

      • Yonis Gómez Peñaranda

        y si se utiliza sentencias SQL como like en el evento keypress de la caja de texto tambien deberia de funcionar.

  • Yonis Gómez Peñaranda

    Hola Condesa, muy buen post.

    Me gustaría darle una utilidad mas en las apk, la idea es tomar lo que has hecho para implantarlo en las aplicaciones como una pantallas Splash.

    Creo que tomando esta idea se podría hacer una Splash screen para nuestras aplicaciones, de tal manera que mostremos un logo o presentación de nuestra apk por un tiempo y luego si cargamos el main.xml y si no es mucho también se podría aplicar a un endSplash cuando se esta cerrando la apk.

    Muchas gracias…

    • Vagprogrammer

      Hola Yonis, tal vez no soy condesa pero mira eso del logo al empezar la aplicación podrías hacerlo utilizando Threads. el problema que eh tenido es que no puedo realizar este tipo de animaciones al iniciar la aplicación, cuando lo intento si aparece el logo pero no hace nada (Condesa?) te dejo el codigo de como poder mostrar un logo estatico al iniciar tu app:

      public class MainActivity extends Activity

      int numerosim=1;

      final Handler mHandler=new Handler();

      protected void miHilo()
      {
      Thread t=new Thread()
      {
      public void run()
      {
      try
      {
      Thread.sleep(2000);
      }
      catch (InterruptedException e)
      {
      e.printStackTrace();
      }
      mHandler.post(ejecutarAccion);
      {

      }
      }
      };
      t.start();
      }

      final Runnable ejecutarAccion= new Runnable()
      {
      public void run()
      {
      comprobacion();
      }
      };

      /** Called when the activity is first created. */
      @Override

      public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.main);

      miHilo();

      }

      public void comprobacion()
      {
      if(numerosim == 0)
      {
      Intent i= new Intent(MainActivity.this, Con_Registro.class);
      startActivity(i);
      }
      else
      {
      Intent i= new Intent(MainActivity.this, Sin_Registro.class);
      startActivity(i);
      }
      finish();
      }
      }

      Ojala y sirva de algo, cuídate :)

      • Yonis Gómez Peñaranda

        Ok, mira el código que yo arregle ya lo mande a androideity para que lo optimice y corrijan algunos bugs que no di para resolver.
        ______________________________________________________________
        //Creamos el proyecto, la clase principal.
        ______________________________________________________________
        package com.yogo.splash;

        import android.app.Activity;
        import android.content.Intent;
        import android.content.pm.ActivityInfo;
        import android.os.Bundle;
        import android.view.Window;
        import android.view.WindowManager;
        import android.view.animation.Animation;
        import android.view.animation.Animation.AnimationListener;
        import android.view.animation.AnimationSet;
        import android.view.animation.AnimationUtils;
        import android.widget.ImageView;

        public class SplashActivityActivity extends Activity {
        /** Called when the activity is first created. */
        AnimationSet animationSet;
        ImageView imagen;

        @Override
        public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
        WindowManager.LayoutParams.FLAG_FULLSCREEN);
        setContentView(R.layout.main);
        imagen = (ImageView) findViewById(R.id.logo);
        configurarAnimacion();
        imagen.startAnimation(animationSet);
        }

        public void configurarAnimacion(){
        animationSet = new AnimationSet(true);

        Animation fadein = AnimationUtils.loadAnimation(this, R.anim.fadein);
        fadein.setDuration(1000);
        Animation fadeout = AnimationUtils.loadAnimation(this, R.anim.feadeout);
        fadeout.setDuration(1000);
        fadeout.setStartOffset(2500);

        animationSet.addAnimation(fadein);
        animationSet.addAnimation(fadeout);
        animationSet.setStartOffset(1000);

        animationSet.setAnimationListener(new AnimationListener(){

        public void onAnimationEnd(Animation animation) {
        // TODO Auto-generated method stub
        //Aqui lanzariamos la siguiente activity, en este caso otra activity llamada menu que no hace nada.
        Intent resultado = new Intent(SplashActivityActivity.this, menu.class);
        startActivity(resultado);
        }

        public void onAnimationRepeat(Animation animation) {
        // TODO Auto-generated method stub
        }

        public void onAnimationStart(Animation animation) {
        // TODO Auto-generated method stub
        imagen.setImageResource(R.drawable.logo);
        }

        });

        }
        }

        ______________________________________________________________
        //creamos otra class android activity para mostrar una ves termina el splash.
        ______________________________________________________________
        package com.yogo.splash;

        import android.app.Activity;
        import android.os.Bundle;

        public class menu extends Activity {
        /**
        * @see android.app.Activity#onCreate(Bundle)
        */
        @Override
        protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // TODO Coloque su código aquí
        setContentView(R.layout.menu);
        }
        }

        ______________________________________________________________
        // El main.xml quedo asi
        ______________________________________________________________

        ______________________________________________________________
        // y el menu.xml quedo asi
        ______________________________________________________________

        ______________________________________________________________

        ahora los archivos que se encargan de las animaciones son 2 xml, que debemos guardar en la carpeta anim.

        // fadein

        //fadeout

        //por ultimo tengo la imagen que voy a mostrar en drawable en cada dpi la llame logo.

        no se como montar la carpeta del código completa aquí, esperemos los Admin del sitio evalúen pronto la idea y la publiquen

      • Anonymous

        Ya también estoy revisando el código fuente que me hizo llegar Yonis en un email :)

  • John Sebastian

    Hola buen día, estoy tratando de hacer una animación con este ejemplo pero cuando la ejecuto solo me muestra la primera imagen de 14 que que hacen todo la animación. Estoy escribiendo el mismo código que tu haces pero no me funciona. El ejercicio lo he realizado en un proyecto nuevo y en otro dentro de un viewswitcher. Pero en los dos tengo el mismo problema. Me podrías ayudar?

    • Anonymous

      Hola, el código de ejemplo de ese tutorial está al final, ye invito a descargarlo para que lo compares con el código que estás utilizando ya que no sabría decirte en qué parte te está fallando tu proyecto :) Saludos!

  • Hansgianfranco

    como puedo enlazar un boton para que al hacerle clock active una animacion de otra activity¿ ayuda! porfavor

    • Anonymous

      No entiendo tu duda. ¿Quieres lanzar una animación de cambio entre activities?

  • Marcela Peña Murallas

    la continuacion de este post??!!
    no hacerlo con imagenes sino con layouts??!!

  • Xavie2a

    Condesa, como podriamos hacer para ejecutar algo (una funcion, un toast, lo que sea) justo al terminar la animacion??

  • Krojb

    Hola que tal como le puedo aumentar mas Frame ya que trato de aumentarle mas pero cuandro lo simulo me manda un error es posible hacer este cambio.

    • Anonymous

      ¿Ya lo agregaste al XML o cómo es que los agregaste?

      • Krojb

        Agrege los comandos <item android:drawable="@drawable/androidx…. en el framen_animation.xml hasta x numero deseado y he agragado las imagenes en la carpeta correspondiente

        • Anonymous

          En teoría no deberías tener ningún problema, ¿qué te dice el logcat o qué error te lanza?

  • killy

    hola como va? queri saber como tengo que hacer para poner un sonido (cualkiera) cuando la animacion esta, por ejemplo, en el segundo png, se puede? alguna idea?

    • condesa

      Se puede, pero no estoy segura si con esta metodología, podrías por ejemplo lanzar otro hilo con la música pero tendrías que crearte también un listener que te avise cuando la animación termine y así terminar también la parte de reproducción de sonido.
      Seguro en stackoverflow encuentras un ejempo.
      Saludos.

      • killy

        gracias!!! ^_^
        y me encanta tus post!!! abrazo!!!!

  • Sarai

    ¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Muchas gracias !!!!!!!!!!!!!!!!
    Lo probé y esta de 10 :) :)
    (Apenas estoy aprendiendo )

  • Jonathan Abc

    Condesa te tengo un reto jeje, tengo un problema que no consigo arreglar y llevo muchísimo buscando en Internet y nadie me da solución, el caso es el siguiente.

    Tengo un texview que va a representar un número y por otro lado un botón, el caso es que al pulsar el botón se va a incrementar en una unidad la cifra que tenga el textview, ahora bien lo que no logro hacer es que mientras tenga el botón pulsado se siga incrementando la cifra y solo pare de incrementarse cuando levante el dedo del botón.

    Si logras darme solución serás mi heroína jaja, sé que hay que tirar de concurrencia y de un runnable por tanto pero no he conseguido construirlo bien.

    Hasta pronto.

    • condesa

      Jajajaja, ok, a mí se me ocurre utilizar el listener OnTouchListener con el cuál puedes utilizar el objeto MotionEvent para saber si te encuentras presionando el botón y cuando ya no lo estás presionando.

      Algo así quedaría:

      button.setOnTouchListener(new OnTouchListener() {

      @Override
      public boolean onTouch(View v, MotionEvent event) {
      switch(event.getAction()){
      case MotionEvent.ACTION_DOWN:
      //Llamas a tu función para incrementar el TextView
      break;
      case MotionEvent.ACTION_UP:
      //Dejas de actualizar el número.
      break;
      }
      return true;
      }
      });

      Eso en teoría podría servir.

      Saludos :)

      • Jonathan Abc

        Hola Condesa lo he probado y no funciona, se comporta como si fuera un onClick normal pero la parte del click sostenido no la hace, aún así mira esta es mi función para actualizar mi TextView

        private void tratarMas(TextView campo, EditText miniCampo){

        int valor=Integer.parseInt(campo.getText().toString()); //CAMPO

        if (miniCampo.getText().toString().equals(“”)){
        campo.setText(String.valueOf(valor + 1) );
        }
        else{
        campo.setText(String.valueOf(valor + Integer.parseInt(miniCampo.getText().toString())) );
        miniCampo.setText(“”);
        }

        }

        Te la pego a pesar de que el error no está aquí, por otro lado en la parte que pones que deje de actualizar el número no sé que hacer pensé en declararme un atributo booleano pulsado, y se actualizaría según el botón esté pulsado o no, tal se haría en los case MotionEvent.

        Así pués en el ACTION_DOWN tendríamos un
        While (pulsado) tratarMas(campo, miniCampo);

        Bueno trás declararme el booleano y tal el programa falla en ejecución supongo q el bucle en cuestión le deja roto.

        Agg qué puedo hacer para arreglar esto, no sé su lo estoy complicando demasiado o qué y sé que lo que has puesto funciona para una app de java convencional, pero como cambian las cosas un poco yo que sé.

        Hasta pronto graciasss !!!

  • Leincy

    Condesa una pregunta las animaciones.. De que maneras se puede hacer la animacion sin necesidad de pulsar un boton.
    Creo el metodo animate al incicio de la aplicacion para que asu vez llame el archivo xml y realize el star del frame, pero no me funciona, si lo coloco los mismo pero en el onclick de un boton si lo hace.. Que podria hacer para funcionar esto.. Por fa

    • condesa

      Pues la solución sería crearte un método que contenga el código para hacer la animación y ya únicamente lo mandas a llamar en dónde lo necesites.

      Saludos

  • Caucasuso33

    Hola Condesa hermosa, me sucede una cosa, cuando meto mas de 18 imagenes, todas iguales, me da un error, es que tiene un limite de memoria o algo?, por que con 18
    frames justas si funciona, por que?

    • condesa

      Eso depende del peso de tus imágenes, por lo demás el número no creo que sea la limitante. Saludos.

  • http://www.facebook.com/Mr.John29 John Martinez

    Hola quisiera crear un botón que me lleve a otra actividad pero que a su vez me reproduzca un sonido pero una sola vez (Algo así como el sonido de un clic en el botón), me podrias colaborar

  • http://www.facebook.com/sheddad.kaidsalahferron Sheddad Kaid-Salah Ferrón

    Hola Condesa.

    Gracias por el artículo. Muy útil.

    Saludos

  • Jorge Yanez

    hola condesa estoy realizando una aplicacion pero lo que deceo hacer es darle un efecto de libro a los layout….! que al deslizar el dedo se comporte como hoja me aria de mucho util tu info…!

  • Jeffrey7

    hola gracias por el tutorial! necesito de alguna manera deterner la animacion en cierto punto… osea que no se repita infinitamente la animacion, necesito que solo se repita una vez y luego se detenga en la ultima imagen de animacion.. alguien me puede decir como lo hago?? gracias

    • Karina Gutiérrez

      Y lo solucionaste?. Tengo la misma pregunta =(