En el Google I/O 15, Google lanzó una librería de diseño que implementa varios componentes estrictamente relacionados con la especificación de Material Design, entre ellos se encuentran nuevos ViewGroups como es el AppbarLayout, CollapsingToolbarLayout y CoordinatorLayout.
Bien combinados y configurados estos Viewgroups pueden ser muy poderosos, aquí van unos ejemplos.
CoordinatorLayout
Como su propio nombre indica, el objetivo y filosofía de este ViewGroup es el de coordinar las vistas de su interior.
Veamos la siguiente imagen:
En este ejemplo se puede apreciar cómo las vistas se coordinan entre sí, a simple vista podemos ver que algunas dependen de otras, por ejemplo, el contenido scrolleable está relacionado con la cabecera y con el FAB.
Veamos el código que conforma este ejemplo:
`
`
Si examinamos el esqueleto de este layout probablemente parezca más sencillo, el CoordinatorLayout tiene únicamente tres hijos: un AppbarLayout, una vista scrolleable y un FloatingActionBar.
Empecemos a examinar estos componentes.
AppBarLayout
Se podría decir que un AppBarLayout es un LinearLayout con superpoderes, los hijos de este ViewGroup se colocan en forma vertical unos debajo de otros que, con ciertos parámetros, permiten aparecer y desaparecer con diferentes animaciones en función del movimiento de scroll que se realice sobre el contenido.
Puede sonar algo confuso al principio, por eso creo que una imagen vale más que mil palabras y si es un .gif, todavía mejor:
El AppBarLayout en este caso es la vista coloreada de azul, colocada debajo de la imagen que se colapsa, contiene un Toolbar, un LinearLayout con el título,un subtítulo y un TabLayout.
Podemos gestionar el comportamiento de los hijos directos de un AppbarLayout con el atributo: layout_scrollFlags. El valor layout_scrollFlags está presente en casi todas las vistas, si no fuera especificado en ninguna, los componentes dentro del AppbarLayout quedarán estáticos permitiendo que el contenido scrollable pase por detrás de esta.
Con el valor: snap, evitamos caer en medios estados logrando que siempre se oculte o expanda el alto total de la vista. El LinearLayout que contiene el texto será mostrado siempre que el usuario haga un movimiento de scroll hacia arriba (valor enterAlways), y el TabLayout, siempre quedará a la vista, ya que no se ha especificado ninguna bandera.
SCROLL_FLAG_ENTER_ALWAYS: When entering (scrolling on screen) the view will scroll on any downwards scroll event, regardless of whether the scrolling view is also scrolling.
SCROLL_FLAG_ENTER_ALWAYS_COLLAPSED: An additional flag for enterAlways which modifies the returning view to only initially scroll back to it's collapsed height.
SCROLL_FLAG_EXIT_UNTIL_COLLAPSED: When exiting (scrolling off screen) the view will be scrolled until it is 'collapsed'.
SCROLL_FLAG_SCROLL: The view will be scroll in direct relation to scroll events.
SCROLL_FLAG_SNAP: Upon a scroll ending, if the view is only partially visible then it will be snapped and scrolled to it's closest edge.
Estos son los parámetros disponibles, de acuerdo a la documentación en Google Developers. De todos modos, mi recomendación es siempre jugar con el ejemplo. En este repositorio se pueden encontrar el conjunto de código de donde se han extraídos los snippets que se muestran en este artículo.
CoordinatorLayout Behaviors
Hagamos una pequeña prueba, vayamos a Android Studio y creamos un proyecto con la siguiente plantilla: Scrolling Activity. Sin hacer ninguna modificación, lo compilamos y esto será lo que nos encontremos:
Si revisamos el código generado, ni en los layouts como en las clases java generadas no encontraremos nada en cuanto a una animación que oculta y muestra el FAB. ¿Por qué?
La respuesta está en el propio código fuente del FloatingActionButton, desde que Android Studio en su v1.2 incluye un decompilador java, hacemos ctrl/cmd + click en el nombre de la clase y ya tendremos el código fuente:
Quien se está encargando de la animación de ocultar y mostrar el FAB es un elemento llamado behavior, en concreto una extensión de CoordinatorLayout.Behavior<FloatingAcctionButton>, el cual, dependiendo de algunos factores, muestra el FAB o no.
Los behaviors, como su propio nombre indican, permiten controlar el comportamiento de los elementos dispuestos dentro de un CoordinatorLayout. Antes hemos mencionado que la filosofía de éste ViewGroup era la de coordinar las vistas de su interior, pues con los behaviors, podremos especificar esta coordinación entre las vistas. Interesante, ¿verdad?.
SwipeDismissBehavior
Sigamos buceando, si buscamos dentro del paquete de la design support library, nos encontraremos con una clase pública llamada: SwipeDismissBehavior. Con este behavior muy fácilmente podremos implementar la funcionalidad swipe to dismiss:
Custom Behaviors
Crear un behavior personalizado no es tan difícil como pueda parecer, únicamente hay que tener en cuenta dos elementos clave: el elemento hijo y dependencia y tener clara la dinámica del CoordinatorLayout.
El hijo es la vista que realzará el comportamiento, la dependencia será quien sirva de disparador para interactuar con el elemento hijo, en el siguiente ejemplo el hijo sería el ImageView del perro y la dependencia el Toolbar, de tal modo que siempre que se mueva el Toolbar se moverá el ImageView.
Para crear un behavior personalizado, lo primero es extender de: CoordinatorLayout.Behavior<T>, siendo T la clase a la que pertenece la vista que nos interese coordinar, posteriormente hay que sobreescribir dos métodos:
- layoutDependsOn
- onDependentViewChanged
El método layoutDependsOn se llamará cada vez que algo ocurra algo en el layout, lo que tendremos que hacer será devolver true cuando se produzcan cambios relacionados con nuestra dependencia, por ejemplo, cuando se haya hecho scroll, de esta forma podremos hacer que nuestra vista hija reaccione en consecuencia.
Siempre que se devuelve true en layoutDependsOn se llamará el segundo método clave: onDependentViewChanged, aquí es donde debemos implementar las animaciones, translaciones o movimientos deseados en nuestra vista hija en función de los parámetros actuales de la dependencia que llega por parámetro.
Recursos
Introduction to coordinator layout on Android - Grzesiek Gajewski