Cómo compilar transiciones atractivas con movimiento de Material para Android

1. Introducción

Material Design es un sistema para crear productos digitales atractivos y llamativos. Mediante la unión de estilo, desarrollo de la marca, interacción y movimiento en un conjunto coherente de principios y componentes, los equipos de productos pueden alcanzar su máximo potencial de diseño.

logo_components_color_2x_web_96dp.png

Los componentes de Material (MDC) ayudan a los desarrolladores a implementar Material Design. MDC, creado por un equipo de ingenieros y diseñadores de UX en Google, cuenta con decenas de componentes de IU atractivos y funcionales, y está disponible para Android, iOS, la Web y Flutter.material.io/develop.

¿Qué es el sistema de movimiento de Material para Android?

El sistema de movimiento de Material para Android es un conjunto de patrones de transición dentro de la biblioteca de MDC-Android que ayuda a los usuarios a comprender y navegar por una app, como se describe en los lineamientos de Material Design.

Estos son los cuatro patrones de transición principales de Material:

  • Transformación de contenedores: genera una transición entre elementos de la IU que incluyen un contenedor; crea una conexión visible entre dos elementos de la IU diferentes mediante una transformación fluida de un elemento en otro.
  • Eje compartido: genera una transición entre elementos de la IU que tienen una relación espacial o de navegación; utiliza una transformación compartida en los ejes X, Y o Z para reforzar la relación entre elementos.
  • Atenuación rápida: genera una transición entre elementos de la IU que no tienen una relación estrecha entre sí; utiliza una atenuación secuencial de entrada y salida, con la escala de un elemento nuevo.
  • Atenuación: se utiliza para los elementos de la IU que entran a los límites de la pantalla o salen de estos.

La biblioteca de MDC-Android ofrece clases de transición para estos patrones, que se compilaron sobre la biblioteca de transiciones de AndroidX (androidx.transition) y el framework de transiciones de Android (android.transition):

AndroidX

  • Disponible en el paquete com.google.android.material.transition
  • Es compatible con el nivel de API 14 y versiones posteriores.
  • Admite Fragments y Views, pero no Activities ni Windows
  • Contiene correcciones de errores retroportadas y un comportamiento coherente en todos los niveles de API

Framework

  • Disponible en el paquete com.google.android.material.transition.platform
  • Es compatible con el nivel de API 21 y versiones posteriores.
  • Admite fragmentos, vistas, actividades y ventanas
  • Las correcciones de errores no se transfirieron a versiones anteriores y pueden tener un comportamiento diferente en los distintos niveles de API

En este codelab, usarás las transiciones de Material que se compilaron sobre la biblioteca de AndroidX, lo que significa que te enfocarás principalmente en los fragmentos y las vistas.

Qué compilarás

En este codelab, usarás Kotlin para compilar algunas transiciones en una app de ejemplo de correo electrónico para Android que se llama Reply. Te guiaremos para que comprendas cómo usar las transiciones de la biblioteca de MDC-Android con el objeto de personalizar el aspecto de tu app.

Se te brindará el código de inicio para la app de Reply, e incorporarás en ella las transiciones de Material que se pueden observar en el siguiente GIF del codelab completo:

  • Transición de transformación de contenedores desde la lista de direcciones de correo electrónico hasta la página de detalles del correo electrónico
  • Transición de transformación de contenedores desde el BAF hasta la página para redactar correos electrónicos
  • Transición de eje Z compartido desde el ícono de búsqueda hasta la página de la vista de búsqueda
  • Transición de fundido entre las páginas de los buzones
  • Transición de transformación de contenedores desde el chip de dirección de correo electrónico hasta la vista de tarjeta

El dominio del iframe solicitado (youtu.be) no se incluyó en la lista de entidades permitidas.

Requisitos

  • Conocimientos básicos sobre el desarrollo de Android y Kotlin
  • Android Studio (descárgalo aquí si todavía no lo tienes)
  • Un emulador o dispositivo Android (disponible a través de Android Studio)
  • El código de muestra (consulta el siguiente paso)

¿Cómo calificarías tu nivel de experiencia con la compilación de apps para Android?

Principiante Intermedio Avanzado

2. Configura tu entorno de desarrollo

Inicia Android Studio

Cuando abras Android Studio, debería aparecer una ventana con el título "Welcome to Android Studio". Sin embargo, si es la primera vez que inicias Android Studio, sigue los pasos del asistente de configuración de Android Studio con los valores predeterminados. En este paso, descargar e instalar los archivos necesarios puede tardar varios minutos. Puedes permitir que se ejecute en segundo plano mientras realizas los pasos de la siguiente sección.

Opción 1: Clona la app de inicio del codelab desde GitHub

Para clonar este codelab desde GitHub, ejecuta los siguientes comandos:

git clone https://github.com/material-components/material-components-android-motion-codelab.git
cd material-components-android-motion-codelab

Opción 2: Descarga el archivo ZIP de la app de inicio del codelab

La app de inicio se encuentra en el directorio material-components-android-motion-codelab-develop.

Cómo cargar el código de inicio en Android Studio

  1. Una vez que finalice el asistente de configuración y aparezca la ventana Welcome to Android Studio, haz clic en Open an existing Android Studio project.

e3f200327a67a53.png

  1. Navega hasta el directorio en el que instalaste el código de muestra y selecciona el directorio de muestra para abrir el proyecto.
  2. Espera un momento para que Android Studio compile y sincronice el proyecto, como se muestra en los indicadores de actividad de la parte inferior de la ventana de Android Studio.
  1. En este punto, es posible que Android Studio genere algunos errores de compilación, ya que te faltan el SDK de Android o las herramientas de compilación, como se muestra más abajo. Sigue las instrucciones de Android Studio para instalar o actualizar estos elementos y sincronizar tu proyecto. Si todavía tienes problemas, sigue la guía para actualizar herramientas con SDK Manager.

6e026ae171f5b1eb.png

Verifica las dependencias del proyecto

El proyecto necesita una dependencia en la biblioteca de MDC-Android. El código de muestra que descargaste ya debería tener esta dependencia, pero verifiquemos la configuración para asegurarnos.

Navega hasta el archivo build.gradle del módulo app y asegúrate de que el bloque dependencies incluya una dependencia en MDC-Android:

implementation 'com.google.android.material:material:1.2.0'

Cómo ejecutar la app de inicio

  1. Asegúrate de que la configuración de compilación ubicada a la izquierda de la elección de dispositivo sea app.
  2. Presiona el botón verde Run/Play para compilar y ejecutar la app.

24218d0a6ae25803.png

  1. En la ventana Select Deployment Target, si ya aparece un dispositivo Android en los dispositivos disponibles, ve al paso 8. De lo contrario, haz clic en Create New Virtual Device.
  2. En la pantalla Select Hardware, selecciona un teléfono, por ejemplo, Pixel 3, y haz clic en Next.
  3. En la pantalla System Image, selecciona una versión reciente de Android, preferentemente, el nivel de API más alto. Si no está instalada, haz clic en el vínculo Download que aparece y completa la descarga.
  4. Haz clic en Next.
  5. En la pantalla Android Virtual Device (AVD), deja los ajustes tal como están y haz clic en Finish.
  6. Selecciona un dispositivo Android en el diálogo de destino de implementación.
  7. Haz clic en Aceptar.
  8. Android Studio compila la app, la implementa y la abre automáticamente en el dispositivo de destino.

¡Listo! El código de inicio para la página principal de Reply debe estar ejecutándose en tu emulador. Deberías ver la carpeta Recibidos con una lista de correos electrónicos.

cc73eb0d0f779035.png

Disminuye las animaciones del dispositivo (opcional)

Como este codelab abarca transiciones rápidas y refinadas, puede resultar útil disminuir las animaciones del dispositivo para observar algunos de los detalles más sutiles de las transiciones durante la implementación. Esto se puede lograr con comandos de shell de adb o con una tarjeta de Configuración rápida. Ten en cuenta que estos métodos para disminuir las animaciones del dispositivo también afectarán las animaciones en el dispositivo fuera de la app de Reply.

Método 1: Comandos del shell de ADB

Para reducir la velocidad de las animaciones del dispositivo en un factor de 10, puedes ejecutar los siguientes comandos desde la línea de comandos:

adb shell settings put global window_animation_scale 10
adb shell settings put global transition_animation_scale 10
adb shell settings put global animator_duration_scale 10

Para restablecer la velocidad de animación del dispositivo a la normalidad, ejecuta los siguientes comandos:

adb shell settings put global window_animation_scale 1
adb shell settings put global transition_animation_scale 1
adb shell settings put global animator_duration_scale 1

Método 2: Tarjeta de Configuración rápida

Como alternativa, para configurar la tarjeta de Configuración rápida, primero habilita la Configuración para desarrolladores en tu dispositivo si no lo hiciste antes:

  1. Abre la app de "Configuración" del dispositivo.
  2. Desplázate hasta la parte inferior y haz clic en "Acerca del dispositivo emulado".
  3. Desplázate hasta la parte inferior y haz clic rápidamente en "Número de compilación" hasta que se habilite la Configuración para desarrolladores.

A continuación, haz lo siguiente, aún en la app de "Configuración" del dispositivo, para habilitar la tarjeta de Configuración rápida:

  1. Haz clic en el ícono de búsqueda o en la barra de búsqueda que se encuentran en la parte superior de la pantalla.
  2. Escribe "tiles" en el campo de búsqueda.
  3. Haz clic en la fila "Tarjetas de configuración rápida para desarrolladores".
  4. Haz clic en el interruptor "Escala de animación de ventana".

Por último, a lo largo del codelab, baja el panel de notificaciones del sistema desde la parte superior de la pantalla y usa el ícono c7e3f98200023f6a.png para alternar entre las animaciones de velocidad lenta y normal.

3. Familiarízate con el código de la app de ejemplo

Echemos un vistazo al código. Proporcionamos una app que usa la biblioteca del componente de Navigation de Jetpack para navegar entre algunos fragmentos diferentes, todo dentro de una sola actividad, MainActivity:

  • HomeFragment: muestra una lista de correos electrónicos.
  • EmailFragment: muestra un solo correo electrónico completo.
  • ComposeFragment: permite redactar un correo electrónico nuevo.
  • SearchFragment: muestra una vista de búsqueda.

Primero, para comprender cómo se configura el gráfico de navegación de la app, abre navigation_graph.xml en el directorio app -> src -> main -> res -> navigation:

<navigation xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:app="http://schemas.android.com/apk/res-auto"
   android:id="@+id/navigation_graph"
   app:startDestination="@id/homeFragment">

   <fragment
       android:id="@+id/homeFragment"
       android:name="com.materialstudies.reply.ui.home.HomeFragment"
       android:label="HomeFragment">
       <argument...>
       <action
           android:id="@+id/action_homeFragment_to_emailFragment"
           app:destination="@id/emailFragment" />
   </fragment>
   <fragment
       android:id="@+id/emailFragment"
       android:name="com.materialstudies.reply.ui.email.EmailFragment"
       android:label="EmailFragment">
       <argument...>
   </fragment>
   <fragment
       android:id="@+id/composeFragment"
       android:name="com.materialstudies.reply.ui.compose.ComposeFragment"
       android:label="ComposeFragment">
       <argument...>
   </fragment>
   <fragment
       android:id="@+id/searchFragment"
       android:name="com.materialstudies.reply.ui.search.SearchFragment"
       android:label="SearchFragment" />
   <action
       android:id="@+id/action_global_homeFragment"
       app:destination="@+id/homeFragment"
       app:launchSingleTop="true"
       app:popUpTo="@+id/navigation_graph"
       app:popUpToInclusive="true"/>
   <action
       android:id="@+id/action_global_composeFragment"
       app:destination="@+id/composeFragment" />
   <action
       android:id="@+id/action_global_searchFragment"
       app:destination="@+id/searchFragment" />
</navigation>

Observa cómo están presentes todos los fragmentos mencionados anteriormente, con el fragmento de inicio predeterminado establecido en HomeFragment a través de app:startDestination="@id/homeFragment". Esta definición en XML del gráfico de destino del fragmento, así como las acciones, informa al código de navegación de Kotlin generado que encontrarás cuando conectes las transiciones.

activity_main.xml

A continuación, observa el diseño activity_main.xml en el directorio app -> src -> main -> res -> layout. Verás el NavHostFragment que se configuró con el gráfico de navegación anterior:

<fragment
   android:id="@+id/nav_host_fragment"
   android:name="androidx.navigation.fragment.NavHostFragment"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   app:defaultNavHost="true"
   app:navGraph="@navigation/navigation_graph"/>

Este NavHostFragment llena la pantalla y controla todos los cambios de navegación de fragmentos de pantalla completa en la app. El BottomAppBar y su FloatingActionButton anclado, también en activity_main.xml, se diseñan sobre el fragmento actual que muestra el NavHostFragment y, por lo tanto, se mostrarán u ocultarán según el destino del fragmento en el código de la app de ejemplo proporcionado.

Además, el BottomNavDrawerFragment en activity_main.xml es un cajón inferior que contiene un menú para navegar entre los diferentes buzones de correo electrónico, que se muestra de forma condicional a través del botón con el logotipo de BottomAppBar Responder.

MainActivity.kt

Por último, para ver un ejemplo de una acción de navegación en uso, abre MainActivity.kt en el directorio app -> src -> main -> java -> com.materialstudies.reply.ui. Ubica la función navigateToSearch(), que debería verse de la siguiente manera:

private fun navigateToSearch() {
   val directions = SearchFragmentDirections.actionGlobalSearchFragment()
   findNavController(R.id.nav_host_fragment).navigate(directions)
}

Esto demuestra cómo navegar a la página de la vista de búsqueda, sin ninguna transición personalizada. Durante este codelab, profundizarás en MainActivity y en cuatro fragmentos principales de Reply para configurar transiciones de Material que funcionen en conjunto con las varias acciones de navegación en toda la app.

Ahora que te familiarizaste con el código de partida, implementemos la primera transición.

4. Agrega una transición de transformación de contenedores desde la lista de direcciones de correo electrónico hasta la página de detalles del correo electrónico

En principio, agregarás una transición para la acción de hacer clic en un correo electrónico. Para este cambio de navegación, se prefiere el patrón de transformación de contenedores, ya que está diseñado para hacer transiciones entre elementos de la IU que incluyen un contenedor. Este patrón crea una conexión visible entre dos elementos de la IU.

Antes de agregar un fragmento de código, prueba ejecutar la app de Reply y hacer clic en un correo electrónico. Debería observarse un corte abrupto y simple, lo que implica que la pantalla se reemplaza por una sin transición:

f0e8a92eb2216bce.gif

Comienza agregando un atributo transitionName en el MaterialCardView en email_item_layout.xml, como se muestra en el siguiente fragmento:

email_item_layout.xml

android:transitionName="@{@string/email_card_transition_name(email.id)}"

El nombre de la transición toma un recurso de cadena con un parámetro. Debes usar el ID de cada correo electrónico para asegurarte de que cada transitionName en nuestro EmailFragment sea único.

Ahora que ya configuraste el nombre de transición del elemento de la lista de correos electrónicos, hagamos lo mismo en el diseño de detalles del correo electrónico. En fragment_email.xml, configura el transitionName de MaterialCardView en el siguiente recurso de cadena:

fragment_email.xml

android:transitionName="@string/email_card_detail_transition_name"

En HomeFragment.kt, reemplaza el código en onEmailClicked por el siguiente fragmento para crear la asignación desde la vista de inicio (elemento de la lista de correos electrónicos) y la vista final (pantalla de detalles del correo electrónico):

HomeFragment.kt

val emailCardDetailTransitionName = getString(R.string.email_card_detail_transition_name)
val extras = FragmentNavigatorExtras(cardView to emailCardDetailTransitionName)
val directions = HomeFragmentDirections.actionHomeFragmentToEmailFragment(email.id)
findNavController().navigate(directions, extras)

Ahora que configuraste la infraestructura, puedes crear una transformación de contenedor. En el método EmailFragment onCreate, configura sharedElementEnterTransition en una nueva instancia de un MaterialContainerTransform (importa la versión com.google.android.material.transition en lugar de la versión com.google.android.material.transition.platform) agregando el siguiente fragmento:

EmailFragment.kt

sharedElementEnterTransition = MaterialContainerTransform().apply {
   drawingViewId = R.id.nav_host_fragment
   duration = resources.getInteger(R.integer.reply_motion_duration_large).toLong()
   scrimColor = Color.TRANSPARENT
   setAllContainerColors(requireContext().themeColor(R.attr.colorSurface))
}

Ahora, prueba volver a ejecutar la app.

ed62cedec31da268.gif

Todo comienza a verse increíble. Cuando haces clic en un correo electrónico de la lista, una transformación de contenedor debe expandir el elemento de la lista en una página de detalles de pantalla completa. Sin embargo, observa cómo, cuando presionas el botón Atrás, el correo electrónico no se contrae en la lista. Además, la lista de correos electrónicos desaparece inmediatamente al comienzo de la transición y muestra el fondo gris de la ventana. Esto significa que aún no terminamos.

Para corregir la transición de regreso, agrega las siguientes dos líneas al método onViewCreated en HomeFragment.kt:

HomeFragment.kt

postponeEnterTransition()
view.doOnPreDraw { startPostponedEnterTransition() }

Intenta volver a ejecutar la app. Si presionas el botón Atrás después de abrir un correo electrónico, este se contraerá y volverá a la lista. ¡Genial! Sigamos mejorando la animación.

El problema de la desaparición de la lista de correos electrónicos se debe a que, cuando se navega a un nuevo Fragment con el componente Navigation, el Fragment actual se quita de inmediato y se reemplaza por el nuevo Fragment entrante. Para que la lista de correos electrónicos siga visible incluso después de que se reemplace, puedes agregar una transición de salida a HomeFragment.

Agrega el siguiente fragmento al método HomeFragment onEmailClicked para que la lista de correos electrónicos se reduzca sutilmente cuando salgas y vuelva a entrar cuando vuelvas a ingresar:

HomeFragment.kt

exitTransition = MaterialElevationScale(false).apply {
   duration = resources.getInteger(R.integer.reply_motion_duration_large).toLong()
}
reenterTransition = MaterialElevationScale(true).apply {
   duration = resources.getInteger(R.integer.reply_motion_duration_large).toLong()
}

A continuación, para asegurarte de que la transición de MaterialElevationScale se aplique a la pantalla principal en su totalidad, en lugar de a cada una de las vistas individuales de la jerarquía, marca el RecyclerView en fragment_home.xml como un grupo de transición.

fragment_home.xml

android:transitionGroup="true"

En esta etapa, la transformación de contenedores debe funcionar por completo. Cuando haces clic en un correo electrónico, el elemento de la lista se expande en una pantalla de detalles y, al mismo tiempo, se desvanece la lista de correos electrónicos. Cuando presionas el botón Atrás, la pantalla de detalles del correo electrónico se contrae en un elemento de la lista mientras se escala verticalmente la lista de correos electrónicos.

9df2b39d5a150418.gif

5. Agrega una transición de transformación de contenedores desde el BAF hasta la página para redactar correos electrónicos

Continuemos con la transformación de contenedores y agreguemos una transición desde el botón de acción flotante (BAF) hasta ComposeFragment expandiendo el BAF a un correo electrónico nuevo que escribirá el usuario. Primero, vuelve a ejecutar la app y haz clic en el BAF a fin de verificar que no se hagan transiciones cuando se inicia la pantalla para redactar correos electrónicos.

d242c9708abd382c.gif

Si bien usamos la misma clase de transición, la forma en que configuramos esta instancia será diferente, ya que nuestro FAB se encuentra en MainActivity y nuestro ComposeFragment se coloca dentro de nuestro contenedor de host de navegación MainActivity.

En ComposeFragment.kt, agrega el siguiente fragmento al método onViewCreated y asegúrate de importar la versión androidx.transition de Slide.

ComposeFragment.kt

enterTransition = MaterialContainerTransform().apply {
   startView = requireActivity().findViewById(R.id.fab)
   endView = emailCardView
   duration = resources.getInteger(R.integer.reply_motion_duration_large).toLong()
   scrimColor = Color.TRANSPARENT
   containerColor = requireContext().themeColor(R.attr.colorSurface)
   startContainerColor = requireContext().themeColor(R.attr.colorSecondary)
   endContainerColor = requireContext().themeColor(R.attr.colorSurface)
}
returnTransition = Slide().apply {
   duration = resources.getInteger(R.integer.reply_motion_duration_medium).toLong()
   addTarget(R.id.email_card_view)
}

Además de los parámetros que se usaron para configurar la transformación del contenedor anterior, aquí se configuran startView y endView de forma manual. En lugar de usar atributos transitionName para que el sistema de transición de Android sepa qué vistas se deben transformar, puedes especificarlas de forma manual cuando sea necesario.

Ahora, vuelve a ejecutar la app. Deberías ver cómo el BAF se transforma en la pantalla para redactar (consulta el GIF al final de este paso).

Al igual que en el paso anterior, debes agregar una transición a HomeFragment para evitar que desaparezca después de que se quite y se reemplace por ComposeFragment.

Copia el siguiente fragmento en el método navigateToCompose de MainActivity antes de la llamada NavController navigate.

MainActivity.kt

currentNavigationFragment?.apply {
   exitTransition = MaterialElevationScale(false).apply {
       duration = resources.getInteger(R.integer.reply_motion_duration_large).toLong()
   }
   reenterTransition = MaterialElevationScale(true).apply {
       duration = resources.getInteger(R.integer.reply_motion_duration_large).toLong()
   }
}

Ya terminaste con este paso. Deberías ver una transición desde el BAF hasta la pantalla para redactar de la siguiente manera:

81b68391ac4b0a9.gif

6. Agrega una transición de eje Z compartido desde el ícono de búsqueda hasta la página de la vista de búsqueda

En este paso, agregaremos una transición desde el ícono de búsqueda hasta la vista de búsqueda directa en pantalla completa. Como no existe un contenedor persistente en este cambio de navegación, se puede usar una transición de eje Z compartido para reforzar la relación espacial entre las dos pantallas y para indicar que se mueva un nivel en dirección ascendente en la jerarquía de la app.

Antes de agregar más fragmentos de código, prueba ejecutar la app y presionar el ícono de búsqueda en la esquina inferior derecha de la pantalla. Debería aparecer la pantalla de la vista de búsqueda sin transición.

499e1a677b4216bb.gif

Para comenzar, busca el método navigateToSearch en MainActivity y agrega el siguiente fragmento de código antes de la llamada al método NavController navigate para configurar las transiciones de salida y reingreso del eje Z de MaterialSharedAxis del fragmento actual.

MainActivity.kt

currentNavigationFragment?.apply {
   exitTransition = MaterialSharedAxis(MaterialSharedAxis.Z, true).apply {
       duration = resources.getInteger(R.integer.reply_motion_duration_large).toLong()
   }
   reenterTransition = MaterialSharedAxis(MaterialSharedAxis.Z, false).apply {
       duration = resources.getInteger(R.integer.reply_motion_duration_large).toLong()
   }
}

A continuación, agrega el siguiente fragmento de código al método onCreate en SearchFragment, que configura sus transiciones MaterialSharedAxis de entrada y salida.

SearchFragment.kt

enterTransition = MaterialSharedAxis(MaterialSharedAxis.Z, true).apply {
   duration = resources.getInteger(R.integer.reply_motion_duration_large).toLong()
}
returnTransition = MaterialSharedAxis(MaterialSharedAxis.Z, false).apply {
   duration = resources.getInteger(R.integer.reply_motion_duration_large).toLong()
}

Por último, para asegurarte de que la transición de MaterialSharedAxis se aplique a la pantalla de búsqueda en su totalidad, en lugar de a cada una de las vistas individuales de la jerarquía, marca el LinearLayout en fragment_search.xml como un grupo de transición.

fragment_search.xml

android:transitionGroup="true"

Eso es todo. Ahora, prueba volver a ejecutar la app y presionar el ícono de búsqueda. Las pantallas de inicio y de la vista de búsqueda deben atenuarse y escalar, de manera simultánea, en el eje Z en profundidad. De esta manera, se crea un efecto fluido entre las dos pantallas.

e5c0b0a130e807db.gif

7. Agrega una transición de atenuación entre las páginas de los buzones

En este paso, agregaremos una transición entre diferentes buzones. Como no deseamos enfatizar una relación espacial ni jerárquica, usaremos un fundido para realizar un "intercambio" sencillo entre las listas de correos electrónicos.

Antes de agregar más fragmentos de código, prueba ejecutar la app, presiona el logotipo de Reply en la barra inferior de la aplicación y cambia los buzones. La lista de correos electrónicos debería cambiar sin transición.

2c874c0a4588e8fb.gif

Para comenzar, busca el método navigateToHome en MainActivity y agrega el siguiente fragmento de código antes de la llamada al método NavController navigate para configurar la transición de salida MaterialFadeThrough del fragmento actual.

MainActivity.kt

currentNavigationFragment?.apply {
   exitTransition = MaterialFadeThrough().apply {
       duration = resources.getInteger(R.integer.reply_motion_duration_large).toLong()
   }
}

A continuación, abre HomeFragment. En onCreate, establece el enterTransition del fragmento en una nueva instancia de MaterialFadeThrough.

HomeFragment.kt

enterTransition = MaterialFadeThrough().apply {
   duration = resources.getInteger(R.integer.reply_motion_duration_large).toLong()
}

Vuelve a ejecutar la app. Cuando abres el panel lateral inferior de navegación y cambias los buzones, se atenúa la lista actual de correos electrónicos y se reduce su escala, mientras que la lista nueva se atenúa y su escala se expande. ¡Genial!

f61dfd58ea7bd3fd.gif

8. Agrega una transición de transformación de contenedores desde el chip de dirección de correo electrónico hasta la vista de tarjetas

En este paso, agregarás una transición que transforma un chip en una tarjeta emergente. Aquí se usa una transformación de contenedor para informar al usuario que la acción que se realiza en la ventana emergente afectará al chip desde el que se originó la ventana emergente.

Antes de agregar un fragmento de código, ejecuta la app de Reply, haz clic en un correo electrónico, haz clic en el botón de acción flotante "reply" y, luego, intenta hacer clic en el chip de contacto de un destinatario. El chip debería desaparecer de inmediato y aparecer una tarjeta con las direcciones de correo electrónico de ese contacto sin animaciones.

6200c682da2382d5.gif

En este paso, trabajarás en ComposeFragment. En el diseño ComposeFragment, ya se agregaron chips de destinatarios (visibles de forma predeterminada) y una tarjeta de destinatario (invisible de forma predeterminada). El chip de destinatario y esta tarjeta son las dos vistas entre las que crearás una transformación de contenedor.

Para comenzar, abre ComposeFragment y busca el método expandChip. Se llama a este método cuando se hace clic en el chip proporcionado. Agrega el siguiente fragmento de código sobre las líneas que intercambian la visibilidad de recipientCardView y chip, lo que activará la transformación del contenedor registrada a través de beginDelayedTransition.

ComposeFragment.kt

val transform = MaterialContainerTransform().apply {
   startView = chip
   endView = binding.recipientCardView
   scrimColor = Color.TRANSPARENT
   endElevation = requireContext().resources.getDimension(
       R.dimen.email_recipient_card_popup_elevation_compat
   )
   addTarget(binding.recipientCardView)
}

TransitionManager.beginDelayedTransition(binding.composeConstraintLayout, transform)

Si ejecutas la app ahora, el chip debería transformarse en una tarjeta de direcciones de correo electrónico para el destinatario. A continuación, configuraremos la transición de regreso para que la tarjeta vuelva a contraerse en el chip.

En el método collapseChip de ComposeFragment, agrega el siguiente fragmento de código para contraer la tarjeta y volver a mostrar el chip.

ComposeFragment.kt

val transform = MaterialContainerTransform().apply {
   startView = binding.recipientCardView
   endView = chip
   scrimColor = Color.TRANSPARENT
   startElevation = requireContext().resources.getDimension(
       R.dimen.email_recipient_card_popup_elevation_compat
   )
   addTarget(chip)
}

TransitionManager.beginDelayedTransition(binding.composeConstraintLayout, transform)

Vuelve a ejecutar la app. Si haces clic en el chip, este se expandirá en una tarjeta, y si haces clic en la tarjeta, esta se contraerá y volverá a convertirse en un chip. ¡Genial!

e823b28e2890e05d.gif

9. Todo listo

Con menos de 100 líneas de código Kotlin y un poco de lenguaje de marcado XML básico, la biblioteca de MDC-Android te ayudó a crear transiciones atractivas en una app existente que cumple con los lineamientos de Material Design y también tiene un aspecto y comportamiento coherentes en todos los dispositivos Android.

454a47ba96017a25.gif

Próximos pasos

Si deseas obtener más información sobre el sistema de movimiento de Material, asegúrate de consultar la especificación y la documentación completa para desarrolladores, y prueba agregar algunas transiciones de Material a tu app.

Gracias por probar el sistema de movimiento de Material. Esperamos que hayas disfrutado de este codelab.

Pude completar este codelab en una cantidad de tiempo y con un nivel de esfuerzo razonables

Totalmente de acuerdo De acuerdo Neutral En desacuerdo Totalmente en desacuerdo

Me gustaría seguir usando el sistema de movimiento de Material en el futuro.

Totalmente de acuerdo De acuerdo Neutral En desacuerdo Totalmente en desacuerdo