MotionLayout y MotionScene: La simpleza de las animaciones cada vez más cerca #AndroidMeetsKotlin
Francisco Manuel López Jurado Colaboraciones 02/11/2018
En el anterior post hiciste uso de ConstraintLayout, ConstraintSet y TransitionManager para hacer animaciones con cierta complejidad en poco tiempo y muy importante, con muy poco código. En esta ocasión vas a tratar con un nuevo componente de Google con el que podrás hacer animaciones con la misma complejidad o más pero sólo con XML. Este componente se llama MotionLayout, ¡vamos allá!.
¿Qué es MotionLayout?
Como su nombre indica, se trata de un layout que posiciona sus elementos de UI y permite que se “muevan”. Si ves la implementación de su clase, puedes observar que extiende de ConstraintLayout y por tanto, se nutre de todas sus propiedades.
Ha sido creado con el fin de acabar con el código de las animaciones (sólo utiliza XML) y el costoso (y feísimo) control de animaciones, en cierto modo, es una unión entre el framework de animaciones, TransitionManager y CoordinatorLayout. Lo primero que se te puede venir a la cabeza es, ¿CoordinatorLayout?, pues sí, este componente tiene una capa de animaciones por defecto basadas en la interacción del usuario (por ejemplo, un scroll).
Como se ha comentado anteriormente, sólo precisa de XML por lo que tiene un carácter completamente declarativo. El objetivo final de este componente será la creación de las animaciones usando una herramienta integrada en Android Studio (vas a llorar de felicidad, y lo sabes), de este modo reduces en gran medida la complejidad a la hora de crearlas y mantenerlas.
¡¡Limitación importante!!
Las animaciones sólo serán aplicables a sus hijos directos y no a otros niveles de jerarquía.
¿Cuándo debo usarlo?
Se debe usar cuando necesites animaciones ante interacciones de los usuarios con los componentes de UI, por ejemplo, un swipe en cualquier dirección.
Dependencia
Necesitas añadir la dependencia de ConstraintLayout en su versión 2 alpha
¿Cómo lo añado al XML?
Simplemente usas:
Es importante saber que MotionLayout se nutre de uno o varios MotionScene para realizar las animaciones. Además, puesto que extiende ConstraintLayout, puedes hacer uso de todas sus propiedades y potencial.
¿Qué es un MotionScene?
Se trata del componente donde configuras tu animación. Puede tener a su vez otros componentes como Transition, ConstraintSet, etc. Estarán alojados en la carpeta “res/xml”.
¿Necesitas saber algo nuevo de ConstraintSet?
No, se tratan de las mismas que usas con ConstraintLayout y sirven para encapsular todas las restricciones necesarias para posicionar un elemento respecto a otro. Puedes crear tantos ConstraintSet como necesites y luego cambiarlas por código, esto provocará animaciones y transiciones al actualizarse sus nuevas restricciones.
Sin más, ¡al turrón!
Ya conoces el escenario y tienes unas ideas básicas para poder crear tu primera animación, para ello vas a implementar la siguiente.
Define tu primer layout usando MotionLayout.
Según has podido ver a lo largo del post, este layout es exactamente igual que ConstraintLayout pero con varias propiedades más, en este caso usarás:
- applyMotionScene. Por defecto está a true, indicará si tienes o no que hacer la escena especificada.
- layoutDescription. Establece la escena para tu animación desde el recurso XML. (@xml/animation_motion_scene)
- showPaths. Muestra la ruta que seguirá la animación. Como es lógico, sólo debes establecerlo a true en debug.
En este caso no necesitas definir ninguna constraint en este layout puesto que irán definidas por completo en la escena que configurará la animación.
El código XML lo encuentras aquí.
Crea tu primer MotionScene
Tendrás 3 grandes componentes:
Transition.
Definirá la animación y bajo qué acción se activará. Las propiedades que vas a usar en este post son:
- constraintSetEnd. Define las constraints para el final de la animación (@+id/motion_constraintset__end).
- constraintSetStart. Define las constraints para el inicio de la animación (@+id/motion_constraintset__start).
- duration. Establece la duración máxima de la animación (700 milisegundos en tu caso).
Además de las propiedades, debes crear tres componentes “onSwipe” (uno por cada vista a animar). Éste será el encargado de configurar cómo se animarán nuestras vistas. En este ejemplo basta con que lo definas con las siguientes propiedades:
- dragDirection. Establece desde qué lado se hace el desplazamiento. Para tu ejemplo será "dragUp". Los valores posibles son: dragUp | dragDown | dragLeft | dragRight.
- touchAnchorId. Establece el id del objeto al que se le aplicará la propiedad “touchAnchorSide”.
- touchAnchorSide. Establece el lado del objeto a mover. Para tu ejemplo será "top". Valores permitidos: top | left | right | bottom.
ConstraintSet de comienzo.
Define las constraints iniciales a las vistas, en tu caso las constraints de inicio harán que las tres imágenes estén en la parte superior.
ConstraintSet de fin.
Define las constraints finales a los mismos componentes, para este ejemplo, las tres imágenes se situarán verticalmente y en el centro.
El código de la escena sería el siguiente.
Vincula el layout con nuestra escena.
Haciendo uso de la propiedad “layoutDescription” podrás establecer la escena a tu layout, después de esto, no tienes que hacer nada más.
Ejecuta el código y verás la siguiente animación (con el path visible).
Pero… ¿No hay código en la vista o en la Activity / Fragment?
No, esta es la magia de MotionLayout, no necesitas nada de código Java o Kotlin para realizar tus animaciones.
Conclusión.
Este nuevo componente te proporciona una nueva forma de enfocar nuestras animaciones donde sólo importa las definiciones por XML. El único problema es que todavía está en alpha y tendrás que esperar un poco más para que finalmente saquen la primera release. Espero que te haya gustado.