Un nuevo tipo de notificación, que ha tomado especial relevancia sobre todo a raíz de la aparición de Android 5 Lollipop y Material Design, son los llamados snackbar. Un snackbar debe utilizarse para mostrar feedback sobre alguna operación realizada por el usuario, y es similar a un toast en el sentido de que aparece en pantalla por un corto periodo de tiempo y después desaparece automáticamente, aunque también presenta algunas diferencias importantes, como por ejemplo que puede contener un botón de texto de acción.
Según las especificaciones del componente dentro de Material Design, un snackbar debe mostrar mensajes cortos, debe aparecer desde la parte inferior de la pantalla (con la misma elevación que el floating action button si existiera, pero menos que los diálogos o el navigation drawer), no debe mostrarse más de uno al mismo tiempo, puede contener un botón de texto para realizar una acción, y normalmente puede descartarse deslizándolo hacia un lateral de la pantalla.
Salvo el último punto, que aclarararemos más adelante, el nuevo componente Snackbar de la librería de diseño se encargará de asegurar todos los demás, y además mantendrá la facilidad de uso de los toast, siendo su API muy similar.
Entrando ya en detalles, lo primero que tendremos que hacer para utilizar los snackbar será añadir la referencia a la nueva librería de diseño a nuestro proyecto:
dependencies { //... compile 'com.android.support:design:22.2.0' }
Hecho esto, para mostrar un snackbar procederemos de una forma muy similar a cómo lo hacíamos en el caso de los toast. Construiremos el snackbar mediante el método estático Snackbar.make() y posteriormente lo mostraremos llamando al método show(). A modo de ejemplo haremos esto desde el evento click de un botón añadido a la aplicación.
En este caso el método make() recibe 3 parámetros. El segundo y el tercero son equivalentes a los ya mostrados para los toast, es decir, el texto a mostrar en el snackbar y la duración del mensaje en pantalla (que en este caso podrá ser Snackbar.LENGTH_SHORT o Snackbar.LENGTH_LONG). El primero requiere más explicación. Como primer parámetro debemos pasar la referencia a una vista que permita al snackbar (navegando hacia arriba por la jerarquía de vistas de nuestro layout) descubrir un «contenedor adecuado» donde alojarse. Este contenedor será normalmente el content view o vista raíz de la actividad, o un contenedor de tipo CoordinatorLayout si se encuentra antes (al final del artículo veremos qué es esto último).
Por tanto, en teoría podríamos pasar en este primer parámetro casi cualquier vista de nuestra actividad (aún no he podido hacer pruebas con layouts complejos). En nuestro caso de ejemplo, aprovechando que creamos el snackbar dentro del evento onClick de un botón pasaremos la referencia al view del botón pulsado que recibimos en el evento:
btnSnackbarSimple.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Snackbar.make(view, "Esto es una prueba", Snackbar.LENGTH_LONG) .show(); } });
Esto es todo lo que hace falta para mostrar un snackbar sencillo, que aparecería en pantalla de la siguiente forma:
Vamos a completar un poco más el ejemplo mostrando también un snackbar con una acción (lanzado desde un segundo botón). Para añadir una acción al snackbar utilizaremos su método addAction(), al que pasaremos como parámetros el texto del botón de acción, y un listener para su evento onClick (análogo al de un botón normal) donde podremos responder a la pulsación del botón realizando las acciones oportunas (en mi caso una simple un simple mensaje de log):
Snackbar.make(view, "Esto es otra prueba", Snackbar.LENGTH_LONG) .setAction("Acción", new View.OnClickListener() { @Override public void onClick(View view) { Log.i("Snackbar", "Pulsada acción snackbar!"); } }) .show();
El botón de acción se mostrará por defecto con el accent color del tema definido para la aplicación (si se ha definido dicho color) o con el color de selección actual. Sin embargo, también podemos especificarlo en la construcción del snackbar mediante el método setActionTextColor(), pasándole directamente un color, o recuperando alguno de los definidos en los recursos de nuestra aplicación mediante getResources().getColor(id_recurso_color):
Snackbar.make(view, "Esto es otra prueba", Snackbar.LENGTH_LONG) //.setActionTextColor(Color.CYAN) .setActionTextColor(getResources().getColor(R.color.snackbar_action)) .setAction("Acción", new View.OnClickListener() { @Override public void onClick(View view) { Log.i("Snackbar", "Pulsada acción snackbar!"); } }) .show();
En el código anterior establecemos un color que hemos definido en el fichero /res/values/colors.xml de la siguiente forma:
<resources> <color name="snackbar_action">#ffff7663</color> </resources>
Y con esto, nuestro nuevo snackbar con acción incluída quedaría de la siguiente forma:
Por último, vamos a pasar de puntillas (por el momento) sobre la posibilidad de descartar un snackbar con el gesto de deslizamiento hacia la derecha. Si intentamos hacer esto sobre cualquiera de los dos ejemplos mostrados hasta ahora veremos que no es posible. Pero si recordáis, antes mencionamos algo de un tipo de contenedor llamado CoordinatorLayout. Este nuevo componente forma también parte de la nueva librería de diseño y puede utilizarse para gestionar de una forma semiautomática algunas de las animaciones habituales de una aplicación android actual, y lo que es más importante, teniendo presente cómo la animación de algún elemento puede afectar a otros. No entraré en mucho detalle por ahora ya que tengo previsto un artículo exclusivo para este tema. Por el momento vamos a conformarnos con saber que si añadimos como elemento padre de nuestro layout un CoordinatorLayout, nuestros snackbar podrán automáticamente descartarse deslizándolos a la derecha. Nuestro layout podría quedar por ejemplo de la siguiente forma:
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" android:paddingBottom="@dimen/activity_vertical_margin" android:orientation="vertical"> <Button android:id="@+id/BtnSimple" android:text="@string/snackbar_simple" android:layout_width="match_parent" android:layout_height="wrap_content" /> <Button android:id="@+id/BtnAccion" android:text="@string/snackbar_accion" android:layout_width="match_parent" android:layout_height="wrap_content" /> </LinearLayout> </android.support.design.widget.CoordinatorLayout>
Si volvemos a ejecutar ahora la aplicación, veremos que todo sigue funcionando de la misma forma que antes, con el añadido de que podremos descartar los mensajes deslizándolos antes de que desaparezcan.
Puedes consultar y/o descargar el código completo de los ejemplos desarrollados en este artículo accediendo a la página del curso en GitHub.
7 comentarios
[…] vamos a mostrar una notificación de tipo snackbar, como ya explicamos en detalle en reciente el artículo dedicado a […]
Tienen buena pinta. Que API Level minimo hace falta para Snackbar? funcionan en Froyo/Gingerbread?
Acabo de verlo. Segun dicen, son retrocompatibles a partir de 2.1: http://android-developers.blogspot.com.es/2015/05/android-design-support-library.html
Salu2!
En el preview del layout pone:
The following classes could not be instantiated:
– android.support.design.widget.CoordinatorLayou
Y no lo pinta, ¿a vosotros os pasa lo mismo?
Hola a tod@s, quisiera saber como poner en marcha el SnackBar pero sin que lo tenga que hacer desde un onClickListener, por ejemplo si quiero informar que no tengo conexión a internet como le paso la View para que funcione?
Gracias :D
Para el comentario de Anderson Suárez. Puedes usar:
Snackbar.make(findViewById(android.R.id.content), «No esta implementado», Snackbar.LENGTH_LONG).show();
Buena explicación, son muy fáciles de utilizar y prácticos