El tutor de nuestro curso online de Desarrollo de Aplicaciones para Android, Víctor Ramírez Las,…
Proyecto Android: transiciones y animaciones con Material Design
4.
Proyecto Android: transiciones y animaciones con Material Design
En este tutorial, vamos a desarrollar un proyecto Android donde mostraremos varias funcionalidades de Material Design, el nuevo lenguaje de diseño implementado con Android 5.0 Lollipop.
En esta aplicación ejemplo, tendremos la posibilidad de seleccionar una película de un listado que presentamos en pantalla, y mostrar información de la misma, utilizando diferentes animaciones asociadas a eventos del usuario sobre la pantalla y transiciones entre activities.
Vemos dos pantallas de la Aplicación (lista de películas y la sinopsis de una de ellas) y un gif animado debajo donde se visualizan esos efectos, al mover y seleccionar una película de la lista:
Se comenzará en primer lugar por enumerar los elementos necesarios para el desarrollo del proyecto que denominaremos «TransicionesAndroidLollipop»:
- Clase SplashScreen, que herede de la clase base Activity, encargada de lanzar una pantalla de presentación al iniciar la aplicación, proporcionando una mayor inmersión del usuario en la aplicación.
- Clase MainActivity, que herede de la clase base Activity, que permite visualizar un listado de películas, que al seleccionar cualquier imagen del listado, mostrará una transición definida con el nuevo estilo material design para lanzar una nueva activity.
- Clase Adaptador, que herede de la clase base BaseAdapter, que sobrescribe una serie de métodos, que permiten construir una vista personalizada para el componente de selección GridView.
- Clase TransicionActivity, que herede de la clase base Activity, que posibilita la lectura de la sinopsis de la película seleccionada, mostrando una transición de entrada y salida al lanzar la nueva activity, además de una animación al pulsar la imagen asociada a la sinopsis.
- Layout
activity_splash_screen.xml
, formado por una componente de tipo ImageView, que mostrará el logotipo de la aplicación. - Layout
activity_main.xml
, formado por un componente de tipo selección GridView, que mostrará un listado de imágenes de grandes películas de la historia. - Layout
activity_transicion.xml
, formado por un TableLayout, donde se definen varias filas formadas por un componente ImageView, que mostrará la imagen seleccionada por el usuario en la activity principal, y en una segunda fila, un componente TextView, que almacenará la sinopsis de la película seleccionada. - Recurso
ripples.xml
, que define el color para la animación de tipo onda al seleccionar una imagen del listado de películas.
Como es habitual, al final del tutorial podrás descargar el código completo del Proyecto
Estructura del proyecto
Documentación código fuente
TransicionesAndroidLollipop\app\src\main\java\com\academiaandroid\transicionesandroidlollipop\MainActivity.java
- Clase que permite visualizar un listado de películas, que al seleccionar
el usuario cualquier imagen del listado, mostrará una transición definida con el nuevo estilo material design para lanzar una nueva activity:
12public class MainActivity extends Activity { - Se comprueba que la versión del SDK es igual o mayor a 21 para establecer la transición de entrada y salida entre activities:
1234567891011121314151617if (Build.VERSION.SDK_INT >= 21) {/*Se habilitan las características de las transiciones.*/getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);/*Se declara e inicializa la clase Transition, que contiene los datos relacionadoscon las animaciones para el cambio de la escena.*/Transition ts_enter = new Explode();/*Se establecen 2 segundos de duración para la transición.*/ts_enter.setDuration(2000);/*Con el método getWindow() se recupera la ventana de la activity quese está ejecutando, estableciendo las transiciones de entrada y salida a la escena.*/getWindow().setEnterTransition(ts_enter);getWindow().setExitTransition(ts_enter);} - Se define el método
lanzarAnimacion
, que será invocado desde el evento encargado de controlar la selección de un ítem de la lista mostrada, y que permite lanzar la nueva activity, enviando los datos de la imagen
seleccionada. Además del intent creado, recibe como argumento un objeto Bundle
para establecer la transición entre las activities que intervienen:
1234567public void lanzarAnimacion(int posicion) {Intent intent = new Intent(MainActivity.this, TransicionActivity.class);intent.putExtra("ImagenSeleccionada", posicion);intent.putExtra("DescripcionSeleccionada", posicion);startActivity(intent, ActivityOptions.makeSceneTransitionAnimation(this).toBundle());}
TransicionesAndroidLollipop\app\src\main\java\com\academiaandroid\transicionesandroidlollipop\TransicionActivity.java
- Clase que permite acceder a la sinopsis de la película seleccionada,
mostrando una transición de entrada y salida al lanzar la nueva activity, además de una animación al pulsar la imagen asociada a la sinopsis:
12public class TransicionActivity extends Activity { - Se comprueba que los valores recibidos de la activity principal no sean nulos, para la construcción de las diferentes animaciones de entrada a la activity que muestre la sinopsis de la película seleccionada:
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657if(bundle != null) {/*Se recuperan las posiciones, tanto de la imagen seleccionada como de la sinopsisinicializada en el array INFO.*/int imagen = bundle.getInt("ImagenSeleccionada");int descripcion = bundle.getInt("DescripcionSeleccionada");/*Se enlaza la variable con su componente a nivel de layout.*/imgvTransicion = (ImageView) findViewById(R.id.imgvVista_Sinopsis);/*Se establece como recurso de la variable imgvTransicion, la imagen seleccionadapor el usuario en la activity principal.*/imgvTransicion.setImageResource(Adaptador.IMAGENES[imagen]);tvDescripcion.setText(INFO[descripcion]);/*Evento lanzado al pulsar sobre el componente ImageView.*/imgvTransicion.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v){if(imgvTransicion != null){imgvTransicion.setSelected(false);imgvTransicion = null;}imgvTransicion = (ImageView)v;v.setSelected(true);/*Se crea una animación indicando entre sus parámetros la vista,el tamaño del ancho y alto, además del radio de inicio y fin. Por último se invoca al métodostart() que lanzará la animación.*/ViewAnimationUtils.createCircularReveal(v,v.getWidth(),v.getHeight()/2,0,v.getHeight() * 2).start();salirAnimacion();}});imgvTransicion.buildDrawingCache();/*Se asigna la imagen seleccionada para la construcción de una paleta de colores dinámica.*/Bitmap bitmap = BitmapFactory.decodeResource(getResources(),Adaptador.IMAGENES[imagen]);if(bitmap != null){/*Se invoca al método asíncrono generateAsync(), que recibe como parámetros la imagen desdela que se extraerá la paleta de colores, además del número de colores y de la instanciaque invocará al método encargado de crear la paleta de colores.*/Palette.generateAsync(bitmap, 32, new Palette.PaletteAsyncListener() {public void onGenerated(Palette palette) {Palette.Swatch swatch = palette.getVibrantSwatch();if (swatch != null) {tvDescripcion.setBackgroundColor(swatch.getRgb());tvDescripcion.setTextColor(swatch.getTitleTextColor());}}});}}
TransicionesAndroidLollipop\app\src\main\java\com\academiaandroid\transicionesandroidlollipop\Adaptador.java
- Clase que sobrescribe una serie de métodos, que permiten construir una vista personalizada para el componente de selección GridView:
1234567891011121314151617181920212223242526public class Adaptador extends BaseAdapter {[...]@Overridepublic View getView(int position, View convertView, ViewGroup parent){if(convertView == null) {/*Se inicializa la clase ImageView, estableciendo el ancho y alto del layouten tiempo de ejecución.*/imgvSinopsis = new ImageView(contexto);imgvSinopsis.setLayoutParams(new GridView.LayoutParams(400,700));imgvSinopsis.setPadding(8, 8, 8, 8);}else{imgvSinopsis = (ImageView)convertView;}/*Se asigna una imagen del array inicializado, a partir de la posición.*/imgvSinopsis.setImageResource(IMAGENES[position]);/*Se establece una sombra para la imagen que se pasa como parámetro, con el valor de elevaciónindicado en el segundo argumento.*/ViewCompat.setElevation(imgvSinopsis,5.0f);/*Devuelve la imagen que se mostrará en cada elemento de la lista.*/return imgvSinopsis;}
TransicionesAndroidLollipop\app\src\main\res\layout\activity_main.xml
- Layout formado por un TableLayout, que mostrará en una de sus filas un componente de tipo selección GridView. Como se puede apreciar en el atributo background, se asigna un recurso xml encargado de mostrar una animación en forma de onda al seleccionar un elemento de la lista de imágenes:
12345678910111213141516171819202122232425[...]<TableLayoutandroid:layout_width="fill_parent"android:layout_height="fill_parent">[...]<TableRowandroid:layout_width="fill_parent"android:layout_height="fill_parent"><GridViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:id="@+id/gvHistorial"android:gravity="center_horizontal"android:background="@drawable/ripples"/></TableRow></TableLayout>[...]
TransicionesAndroidLollipop\app\src\main\res\layout\activity_transicion.xml
- Layout formado por un TableLayout, donde se definen varias filas formadas por un componente ImageView, que mostrará la imagen seleccionada por el usuario en la activity principal, y en una segunda fila, un componente TextView, que almacenará la sinopsis de la película seleccionada. Como características principales dentro de este layout, se define una vista principal (elemento
ScrollView
) que permitirá desplazarse de manera vertical por la pantalla para poder visualizar la información que muestra, además de asignar un valor al atributofontFamily
del componente TextView, que se puede encontrar en el nuevo tema Material:
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"android:id="@+id/ScrollView01"android:layout_width="fill_parent"android:layout_height="fill_parent" >[...]<TableLayoutandroid:layout_width="fill_parent"android:layout_height="fill_parent"><TableRowandroid:layout_width="fill_parent"android:layout_height="fill_parent"><ImageViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:id="@+id/imgvVista_Sinopsis"android:contentDescription="@string/logo"android:layout_marginBottom="10dp" /></TableRow><TableRowandroid:layout_width="fill_parent"android:layout_height="fill_parent"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="@string/vacio"android:id="@+id/tvDescripcion"android:scrollbars="vertical"android:maxLines="100"android:textStyle="bold|italic"android:textAlignment="viewStart"android:nestedScrollingEnabled="false"android:fontFamily="@android:style/TextAppearance.Material.Title"android:textColor="#97dcebff"android:focusableInTouchMode="false" /></TableRow></TableLayout>[...]</ScrollView>
Dependencias declaradas:
Para este proyecto ha sido necesario añadir las siguientes dependencias para la compatibilidad de apps con la API de nivel 21, además de establecer soporte con la librería Palette para extraer colores de una imagen (archivo «build.gradle» del módulo «app»):
1 2 3 4 5 |
dependencies { [...] compile 'com.android.support:appcompat-v7:21.0.3' compile 'com.android.support:palette-v7:21.0.3' } |