¿Qué es Motion Layout y cómo se utiliza?

¿Qué es Motion Layout y cómo se utiliza?

Tras la llegada de Material Design han sido muchas las librerías que se han añadido para aplicar animaciones cada vez más refinadas tanto a los elementos de la interfaz como en las transiciones entre pantallas. Ejemplos como el CoordinatorLayout, un tipo de layout que proporciona un nivel adicional de control sobre eventos táctiles entre vistas secundarias, o el ConstraintLayout capaz de crear layouts complejos con una jerarquía de vistas plana, es decir, sin grupos de vistas anidadas.

Pues bien, de estas nuevas incorporaciones nace en 2018 MotionLayout, una clase que extiende de la ya comentada ConstraintLayout y que nos permite  administrar las animaciones de movimiento y widgets en nuestra app.

Si quieres saber más sobre cómo animar layouts con MotionLayout, sus características y su potencial para ponerlo en práctica en cualquier aplicación, en este post te explicaremos las claves para dar tus primeros pasos con este potente tipo de vista.

¿Qué es Motion Layout?

Como decíamos, MotionLayout es una subclase de ConstraintLayout  que ayuda a administrar animaciones de movimiento y widgets en nuestra app. Grosso modo, MotionLayout está diseñado para mover, cambiar el tamaño y animar los elementos de la IU con los que interactúan los usuarios.

Como parte de la biblioteca de ConstraintLayout, MotionLayout está disponible como una biblioteca de compatibilidad y es compatible con versiones anteriores a la API nivel 14.

Al ser MotionLayout una subclase de ConstraintLayout es posible transformar cualquier ConstraintLayout existente en un MotionLayout simplemente reemplazando el nombre de la clase en tu archivo. 

Para llevar a cabo estas animaciones MotionLayout admite transiciones entre varios estados (ConstraintSet) que previamente han sido definidos en MotionScenes

¿Cómo se usa?

1. Incluir la dependencia al proyecto

dependencies { implementation 'androidx.constraintlayout:constraintlayout:2.0.0-beta1' }


2. Añadimos el componente MotionLayout incluyendo la referencia al MotionScene.

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.motion.widget.MotionLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/motionLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layoutDescription="@xml/scene_01">
</androidx.constraintlayout.motion.widget.MotionLayout>


3. Añadimos el MotionScene: un archivo XML incluido en la carpeta de recursos que contiene todas las descripciones de movimientos para el diseño correspondiente. En este archivo deberemos de prestar atención a lo siguiente:

  • <Transition> tiene la definición básica del movimiento. En esta parte incluiremos las referencias a los extremos del movimiento: motion:constraintSetStart y motion:constraintSetEnd. También incluiremos el tiempo de gesto al que queremos que reaccione nuestra animación, en el ejemplo <OnSwipe>, junto con la referencia a la vista (motion:touchAnchorId):
<MotionScene
xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:motion="http://schemas.android.com/apk/res-auto">

    <Transition
        app:constraintSetEnd="@id/end"
        app:constraintSetStart="@id/start"
        app:duration="1000">

        <OnSwipe
            app:dragDirection="dragUp"
            app:touchAnchorId="@id/button"
            app:touchAnchorSide="top" />

    </Transition>
</MotionScene>


4. En el mismo archivo de MotionScene añadimos los <ConstraintSet> donde se definirán las diversas restricciones que describen tu movimiento.

<MotionScene
xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:motion="http://schemas.android.com/apk/res-auto">

    <Transition
        app:constraintSetEnd="@id/end"
        app:constraintSetStart="@id/start"
        app:duration="1000">

        <OnSwipe
            app:dragDirection="dragUp"
            app:touchAnchorId="@id/button"
            app:touchAnchorSide="top" />
    </Transition>
    <ConstraintSet android:id="@id/start">
        <Constraint
           android:id="@id/button"
           android:layout_width="64dp"
           android:layout_height="64dp"
           android:layout_marginStart="8dp"
           motion:layout_constraintBottom_toBottomOf="parent"
           motion:layout_constraintStart_toStartOf="parent"
           motion:layout_constraintTop_toTopOf="parent"/>
     </ConstraintSet>

     <ConstraintSet android:id="@id/end">
        <Constraint
           android:id="@id/button"
           android:layout_width="64dp"
           android:layout_height="64dp"
           android:layout_marginEnd="8dp"
           motion:layout_constraintBottom_toBottomOf="parent"
           motion:layout_constraintEnd_toEndOf="parent"
           motion:layout_constraintTop_toTopOf="parent"/>
     </ConstraintSet>
</MotionScene>


Los elementos ConstraintSet pueden contener atributos adicionales que se interpolan durante la transición. Además de la posición y los límites, MotionLayout interpola los siguientes atributos:

  • alpha
  • visibility
  • elevation
  • rotation, rotationX, rotationY
  • translationX, translationY, translationZ
  • scaleX, scaleY


CustomAttribute

En los ConstraintsSets de inicio y fin es posible añadir un elemento <CustomAttribute> en donde se puede especificar una transición para los atributos que no están simplemente relacionados con la posición o los atributos View. El <CustomAttribute> contiene dos atributos propios:

  • motion:attributeName: es obligatorio y debe coincidir con un objeto que tenga métodos get y set.
  • El otro atributo que debes proporcionar se basa en el tipo de valor. Elige entre los siguientes tipos admitidos (customColorValue, customIntegerValue, customFloatvalue, customStringValue. customDimension, customBoolean)


KeyFrame

Otro atributo interesante de los MotionScences es la posibilidad de usar KeyFrames. Los <KeyFrame>, también llamados “fotogramas clave”, permiten especificar un cambio en un momento determinado durante la transición.

Gracias a los KeyFrames es posible tener un estado intermedio: un estado por el que pasar, pero no un estado al que pertenecer (como los ConstraintSets de start/end). 

De forma parecida al <CustomAttribute>, los <KeyFrames> también permiten varios tipos:

  • De posición: KeyPosition
  • De atributo: KeyAttribute
  • De KeyCycle: KeyCycle
  • De TimeCycle: KeyTimeCycle

Todos los tipos tienen una serie de atributos comunes

  • motion:framePosition: define cuándo se aplica el keyFrame durante la transición (de 0 a 100)
  • motion:target: define el objeto que se ve afectado por este keyFrame 
  • motion:transitionEasing: se define el tipo de curva de aceleración (el valor predeterminado es lineal)
  • motion:curveFit: spline (predeterminado) o lineal: la curva de interpolación que se ajusta a los fotogramas clave. El valor predeterminado es una curva spline monótona, lo que hace que las transiciones sean más suaves, pero puede decidir tener segmentos lineales en su lugar.


¿Por qué keyFrames si los ConstraintSets permiten mover cualquier widget de una forma muy flexible?

  • Los keyFrames definen una modificación transitoria, mientras que los ConstraintSets definen un estado de «reposo».
  • Los keyFrames son más ligeros que los ConstraintSet porque definen solo el atributo que queremos modificar.
  • Los keyFrames de tipo posición permiten manipular la ruta de movimiento de un widget; los ConstraintSets definen la posición de un widget,  pero en relación con otros widgets.


¿Dónde podrían usarse?

MotionLayout puede funcionar por sí mismo o combinándolos con otros componentes como:

  • CoordinatorLayout
  • DrawerLayout 
  • ViewPager

Aunque realmente MotionLayout podría imitar el comportamiento de alguno de estos componentes. Combinarlos sirve, sobre todo, para dar calidad a componentes que ya están planteados y estructurados.

Con un gran potencial

Como hemos visto en el post, MotionLayout es uno de los tipos de vistas más potentes en relación al uso y gestión de las animaciones. 

Tanto en la versión básica (utilizando constraintsSets start y end) como añadiendo keyframes que enriquezcan la animación, las vistas con este tipo de Layout quedarán especialmente vistosas y en base a los principios de Material Design.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

« »