Crea tu propia Snackbar personalizada

Fabio Negri
Droid LATAM
Published in
4 min readJul 26, 2020

Una de las cosas que más me gusta sobre Android es la gran cantidad de posibilidades para personalizar nuestras apps que nos proveen tanto el propio framework como las librerías de diseño. Desde botones flotantes hasta selectores, diálogos, animaciones o transiciones. Y si ninguno de ellos encaja con nuestras necesidades, tenemos la posibilidad de crear nuestros propios componentes sin ningún tipo de problema.

Hace un tiempo estuve trabajando en un proyecto personal y quería personalizar un Snackbar.

Los Snackbars proveen una respuesta visual ante una operación o evento. Muestran un breve mensaje en la parte inferior de la pantalla de dispositivos móviles o en la inferior izquierda en dispositivos más grandes. Aparecen por encima del resto de los elementos en pantalla y sólo uno puede ser mostrado a la vez.

A pesar de que podemos personalizarla, tal vez sintamos que las opciones que nos ofrece no son lo suficiente como para que su estilo encaje con el del resto de nuestra aplicación… y eso fue lo que me pasó.
Por suerte podemos crear nuestra propia Snackbar con la ayuda de unas pocas clases.

Entonces, ¿por dónde comenzamos?

Lo primero que podemos hacer es echar un vistazo al código fuente del Snackbar para darnos una idea de cómo funciona. Al primer vistazo puede parecer un poco confuso, pero veremos que no es tan complicado como parece. Hay 3 puntos que me gustaría remarcar:

  • Extiende de BaseTransientBottomBar, a la cual le provee como parámetros de constructor una parent view, una vista de contenido y un callback de tipo ContentViewCallback .
  • Tiene un factory method llamado make() como principal punto de entrada. Este método se encarga de buscar una vista parent adecuada para el contenido, de generar nuestra vista y de asignarle varias de las propiedades que mostrará más tarde.
  • Por último, una serie de funciones para personalizarla.

Ahora que ya conocemos cómo funciona su implementación, ¡es momento de crear nuestra propia Snackbar!

Paso 1: Crear nuestra vista personalizada

Lo primero que debemos hacer es crear nuestra propia vista, que se va a mostrar en el inferior de la pantalla, junto con su respectivo layout. En nuestro caso consistirá simplemente de una imagen estática y un mensaje. Debería verse algo como:

y el archivo .xml:

Paso 2: Hacer que la vista implemente ContentViewCallback

El siguiente paso es hacer que nuestra vista implemente la interfaz ContentViewCallback. Esta interfaz se encarga de notificarnos cuando la Snackbar comience a aparecer y cuando comience a desaparecer (animateContentIn() y animateContentOut respectivamente).

Como puedes ver, simplemente agregué una sencilla animación de escalado para cuando la Snackbar aparezca. También deshabilité el atributo clipToPadding para evitar que la imagen se recorte como consecuencia del efecto que genera el OvershootInterpolator.

Paso 3: Extender de BaseTransientBottomBar

El último paso es crear el equivalente de la clase Snackbar.

Para ello, el constructor de nuestra clase personalizada recibirá dos parámetros: uno para la vista padre y otro para la vista que implementa la interfaz ContentViewCallback (la que creamos en el paso 2).

class ChefSnackbar(
parent: ViewGroup,
content: ChefSnackbarView
) : BaseTransientBottomBar<ChefSnackbar>(parent, content, content)

Luego tendremos que crear nuestro punto de entrada, eso que anteriormente llamamos factory method, que servirá nada más y nada menos que para devolvernos una instancia de nuestra Snackbar. Como vimos anteriormente, este método debe hacer 3 cosas:

  • Encontrar la mejor vista para ubicar nuestra propia Snackbar: no nos vamos a poner creativos aquí y reinventar la rueda, sino que para lograrlo "tomaremos prestada" la lógica que encontramos en el código fuente de Snackbar. La única modificación que haremos es convertirla en una extension function de la clase View.
  • Generar nuestra vista personalizada: Me parece mucho mejor crear nuestra vista a través de un archivo .xml, así de esta forma puedo cambiar fácilmente sus atributos o incluso crear un estilo.
  • Y finalmente, construir y retornar nuestra Snackbar.

Con todo esto, el código debería verse como el siguiente:

Notemos en el código que si falla en encontrar una vista padre adecuada, arroja una excepción de tipo IllegalArgumentException, así que asegúrate de pasar una vista válida cuando intentes construir tu Snackbar.

Si corres este código, vas a ver un fondo gris y un espaciado que no deberían estar. Esto sucede porque la implementación de BottomTransientBar envuelve a nuestra vista dentro de un SnackbarBaseLayout con un theme particular. La forma más fácil de solucionar este problema es agregando las siguientes líneas en el bloque init:

init {
getView().setBackgroundColor(ContextCompat.getColor(view.context, android.R.color.transparent))
getView().setPadding(0, 0, 0, 0)
}

Para resumir, el código final debería ser como el siguiente:

Para mostrar el Snackbar, sólo hay que llamar:

ChefSnackbar.make(aView).show()

y deberíamos ver algo como esto:

Un ejemplo de Snackbar personalizada

¡Listo! ¡Tenemos nuestra propia Snackbar funcionando!

Puedes encontrar el código completo con un ejemplo en Github.

¡Espero que les haya gustado!

--

--