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.
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 MDC-Android que puede ayudar a los usuarios a comprender una app y navegar por ella, 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, compilados 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
- Admite el nivel de API 14 y versiones posteriores
- Admite fragmentos y vistas, pero no admite actividades ni ventanas
- Contiene correcciones de errores portados y un comportamiento coherente en todos los niveles de API.
Framework
- Disponible en el paquete
com.google.android.material.transition.platform
- Compatible con el nivel de API 21 y versiones posteriores
- Admite fragmentos, vistas, actividades y ventanas.
- Las correcciones de errores no se portaron a versiones anteriores y pueden tener un comportamiento diferente en los diferentes niveles de API.
En este codelab, usarás las transiciones de Material compiladas 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 llamada Reply. Te guiaremos para que comprendas cómo usar las transiciones de la biblioteca MDC-Android para 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 tarjetas
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?
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
- 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.
- Navega hasta el directorio en el que instalaste el código de muestra y selecciona el directorio de muestra para abrir el proyecto.
- 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.
- 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.
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
- Asegúrate de que la configuración de compilación ubicada a la izquierda de la elección de dispositivo sea
app
. - Presiona el botón verde Run/Play para compilar y ejecutar la app.
- En la ventana Select Deployment Target, si ya tienes un dispositivo Android en la lista de dispositivos disponibles, ve al Paso 8. De lo contrario, haz clic en Create New Virtual Device.
- En la pantalla Select Hardware, selecciona un teléfono, por ejemplo, Pixel 3, y haz clic en Next.
- 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.
- Haz clic en Next.
- En la pantalla Android Virtual Device (AVD), deja los ajustes tal como están y haz clic en Finish.
- Selecciona un dispositivo Android en el diálogo de destino de la implementación.
- Haz clic en Aceptar.
- 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.
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 los comandos de shell de adb
o 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 de shell de ADB
Para disminuir la velocidad de las animaciones del dispositivo hasta 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 aún no lo hiciste:
- Abre la app de "Configuración" del dispositivo
- Desplázate hasta la parte inferior y haz clic en "Acerca del dispositivo emulado".
- Desplázate hacia abajo y haz clic rápidamente en "Número de compilación" hasta que se habilite la configuración para desarrolladores
A continuación, sigue estos pasos, aún en la app de "Configuración" del dispositivo, para habilitar la tarjeta de Configuración rápida:
- Haz clic en el ícono de búsqueda o en la barra de búsqueda que se encuentra en la parte superior de la pantalla.
- Escribe "tarjetas" en el campo de búsqueda.
- Haz clic en la fila “Tarjetas de configuración rápida para desarrolladores”.
- Haz clic en el interruptor "Escala de animación de ventana"
Por último, a lo largo del codelab, desliza el panel de notificaciones del sistema desde la parte superior de la pantalla y usa el ícono 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.
navigation_graph.xml
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 lanzamiento predeterminado establecido en HomeFragment
a través de app:startDestination="@id/homeFragment"
. Esta definición XML del gráfico de destino del fragmento, así como las acciones, informa el código de navegación de Kotlin generado que encontrarás cuando conectes 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 está configurado con el gráfico de navegación de arriba:
<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
ocupa toda 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 disponen sobre el fragmento actual que muestra el NavHostFragment
y, por lo tanto, el código de la app de ejemplo proporcionado los mostrará u ocultarán según el destino del fragmento.
Además, BottomNavDrawerFragment
en activity_main.xml
es un panel lateral inferior que contiene un menú para navegar entre los diferentes buzones de correo electrónico, que se muestra condicionalmente a través del botón del logotipo de Responder BottomAppBar
.
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
. Busca 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)
}
Aquí se muestra cómo puedes navegar a la página de vista de búsqueda sin ninguna transición personalizada. Durante este codelab, profundizarás en MainActivity de Reply y cuatro fragmentos principales para configurar transiciones de Material que funcionen en conjunto con las diversas acciones de navegación de 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:
Primero, agrega un atributo transitionName
en el MaterialCardView
de 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 cadenas 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 configuraste el nombre de transición del elemento de la lista de correos electrónicos, hagamos lo mismo en el diseño de los detalles del correo electrónico. En fragment_email.xml
, configura el transitionName
de MaterialCardView
en el siguiente recurso de cadenas:
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 de 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 tienes configurada la canalización, puedes crear una transformación de contenedor. En el método onCreate
de EmailFragment
, establece sharedElementEnterTransition
en una instancia nueva de 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.
Todo comienza a verse increíble. Cuando haces clic en un correo electrónico de la lista, una transformación de contenedor debería expandir el elemento de la lista a una página de detalles en pantalla completa. Sin embargo, observa que presionar el botón Atrás no contrae el correo electrónico nuevamente en la lista. Además, la lista de direcciones de correo electrónico desaparece inmediatamente al comienzo de la transición y muestra el fondo de la ventana gris. Esto significa que aún no terminamos.
Para corregir la transición de retorno, agrega las siguientes dos líneas al método onViewCreated
en HomeFragment.kt
:
HomeFragment.kt
postponeEnterTransition()
view.doOnPreDraw { startPostponedEnterTransition() }
Vuelve a ejecutar la app. Si presionas Atrás después de abrir un correo electrónico, este se contraerá en la lista. ¡Genial! Sigamos mejorando la animación.
El problema de que la lista de direcciones de correo electrónico desaparezca es que, cuando navegas a un nuevo fragmento usando el componente de Navigation, el fragmento actual se quita de inmediato y se reemplaza por el nuevo fragmento entrante. Para mantener la lista de direcciones de correo electrónico visible incluso después de reemplazarla, puedes agregar una transición de salida a HomeFragment
.
Agrega el siguiente fragmento al método onEmailClicked
de HomeFragment
para que la lista de correos electrónicos se reduzca sutilmente cuando salgas y se vuelva a ingresar cuando se vuelva 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 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.
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 del botón de acción flotante a 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.
Si bien usamos la misma clase de transición, la forma en que configuramos esta instancia será diferente, ya que nuestro BAF 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 nuestra transformación de contenedores anterior, aquí se establecen startView
y endView
de forma manual. En lugar de usar atributos transitionName
para permitir que el sistema de transición de Android sepa qué vistas se deben transformar, puedes especificarlos de forma manual cuando sea necesario.
Ahora, vuelve a ejecutar la app. Deberías ver que el BAF se transforma en la pantalla de redacción (observa 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 quitarse y reemplazarse por ComposeFragment
.
Copia el siguiente fragmento en el método navigateToCompose
en MainActivity
antes de llamar a 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:
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.
Para comenzar, busca el método navigateToSearch
en MainActivity
y agrega el siguiente fragmento de código antes de la llamada de método NavController
navigate
para configurar la salida del fragmento actual y volver a ingresar las transiciones del eje Z MaterialSharedAxis
.
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 de entrada y salida MaterialSharedAxis
.
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 garantizar que la transición de MaterialSharedAxis
se aplique a toda la pantalla de búsqueda, en lugar de a cada una de las vistas individuales de la jerarquía, marca 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.
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.
Para comenzar, busca el método navigateToHome
en MainActivity
y agrega el siguiente fragmento de código antes de la llamada al método navigate
NavController
para configurar la transición MaterialFadeThrough
de salida 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!
8. Agrega una transición de transformación de contenedores del chip de dirección de correo electrónico a la vista de tarjeta
En este paso, agregarás una transición que transforme un chip en una tarjeta emergente. Aquí se usa una transformación de contenedor para informar al usuario que la acción realizada en la ventana emergente afectará al chip donde 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 FAB "Responder" y, luego, intenta hacer clic en el chip de contacto de un destinatario. El chip debería desaparecer de inmediato y debería aparecer una tarjeta con las direcciones de correo electrónico de ese contacto sin animaciones.
En este paso, trabajarás en ComposeFragment
. Ya se agregaron al diseño ComposeFragment
chips de destinatarios (visibles de forma predeterminada) y una tarjeta de destinatario (invisible de forma predeterminada). Un 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 recipientCardView
y chip
, que activará la transformación de 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 devolución para volver a contraer la tarjeta en el chip.
En el método collapseChip
de ComposeFragment
, agrega el siguiente fragmento de código para contraer la tarjeta en 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, se debería expandir el chip a una tarjeta, mientras que si haces clic en ella, la tarjeta se contraerá de nuevo en el chip. ¡Genial!
9. Todo listo
Con menos de 100 líneas de código Kotlin y algunos elementos de marcado XML básicos, 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.
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.