Codelab de Compose para Wear OS

1. Introducción

4d28d16f3f514083.png

Compose para Wear OS te permite trasladar el conocimiento que aprendiste compilando apps en dispositivos móviles con Jetpack Compose a dispositivos wearable.

Con la compatibilidad integrada de Material You, Compose para Wear OS simplifica y acelera el desarrollo de IU (al igual que en dispositivos móviles) y te ayuda a crear apps atractivas con menos código.

Se espera que, para realizar este codelab, tengas conocimientos previos sobre Compose, pero no necesitas ser experto.

Crearás varios elementos que admiten composición específica para Wear (tanto simples como complejos) y, cuando termines, podrás comenzar a escribir tus propias apps para Wear OS. Comencemos.

Qué aprenderás

  • Similitudes o diferencias entre Compose en dispositivos móviles y Wear OS
  • Elementos de Wear OS que admiten composición similares a elementos comunes que admiten composición de dispositivos móviles
  • Nuevos elementos de Wear OS que admiten composición
  • LazyColumn de Wear OS (ScalingLazyColumn)
  • La versión de Scaffold de Wear OS

Qué compilarás

Compilarás una app simple que muestre una lista desplazable de elementos optimizados que admiten composición para Wear OS.

Dado que usarás Scaffold, también obtendrás un tiempo de texto curvo en la parte superior, una viñeta y, por último, un indicador de desplazamiento vinculado al lado de el dispositivo.

A continuación, se muestra cómo lucirá la tarjeta cuando hayas terminado el codelab:

b7bd20036af4859d.gif

Requisitos previos

2. Cómo prepararte

En este paso, configurarás tu entorno y descargarás el proyecto inicial.

Qué necesitarás

  • La versión estable más reciente de Android Studio
  • Un dispositivo o emulador de Wear OS (¿Es la primera vez? Aquí te indicamos cómo configurarlo)

Cómo descargar el código

Si ya instalaste git, solo ejecuta el siguiente comando para clonar el código de este repositorio. Para comprobarlo, escribe git --version en la terminal o línea de comandos y verifica que se ejecute de forma correcta.

git clone https://github.com/googlecodelabs/compose-for-wear-os.git
cd compose-for-wear-os

Si no tienes Git, puedes hacer clic en el siguiente botón a fin de descargar todo el código de este codelab:

Descargar ZIP

En cualquier momento, puedes ejecutar cualquiera de los módulos en Android Studio si realizas cambios en la configuración de ejecución de la barra de herramientas.

8a2e49d6d6d2609d.png

Cómo abrir el proyecto en Android Studio

  1. En la ventana Welcome to Android Studio, selecciona 1f5145c42df4129a.png Open an Existing Project.
  2. Selecciona la carpeta [Download Location].
  3. Cuando Android Studio haya importado el proyecto, prueba si puedes ejecutar los módulos start y finished en un emulador de Wear OS o un dispositivo físico.
  4. El módulo start debería verse como en la siguiente captura de pantalla. En este módulo, realizarás todo el trabajo.

7668d2915856b849.png

Cómo explorar el código de inicio

  • build.gradle contiene la configuración básica de una app. Incluye las dependencias necesarias para crear una app de Wear OS que admita composición. Analizaremos las similitudes y las diferencias entre Jetpack Compose en dispositivos móviles y Wear OS.
  • main > AndroidManifest.xml incluye los elementos necesarios para crear una aplicación de Wear OS. Esta es una app distinta de Compose y es similar a una app para dispositivos móviles, por lo que no la revisaremos.
  • La carpeta main > theme/ contiene los archivos Color, Type y Theme que Compose usa para el tema.
  • main > MainActivity.kt contiene código estándar para crear una app con Compose. Además, contiene los elementos de nivel superior que admiten composición (como Scaffold y ScalingLazyList) para nuestra app.
  • main > ReusableComponents.kt contiene funciones para la mayoría de los elementos de Wear que admiten composición que crearemos. En este archivo, trabajaremos mucho.

3. Cómo consultar las dependencias

La mayoría de los cambios de dependencias relacionados con Wear se realizarán en las capas de arquitectura superiores (destacadas en rojo a continuación).

d92519e0b932f964.png

De esa manera, muchas de las dependencias que ya usas con Jetpack Compose no cambian cuando se segmentan a Wear OS. Por ejemplo, las dependencias de IU, tiempo de ejecución, compilador y animación permanecerán iguales.

Sin embargo, deberás utilizar las bibliotecas adecuadas de Material, Foundation y Navigation de Wear OS, a diferencia de las que usaste anteriormente en tu app para dispositivos móviles.

A continuación, se ofrece una comparación para aclarar las diferencias:

Dependencia de Wear OS(androidx.wear.*)

Comparación

Dependencia de dispositivos móviles(androidx.*)

androidx.wear.compose:compose-material

en lugar de

androidx.compose.material:material

androidx.wear.compose:compose-navigation

en lugar de

androidx.navigation:navigation-compose

androidx.wear.compose:compose-foundation

además de

androidx.compose.foundation:foundation

1. Los desarrolladores pueden continuar utilizando otras bibliotecas relacionadas con Material, como la ondulación y los íconos de material que se extienden con la biblioteca Wear Compose Material.

Abre build.gradle y busca "TODO: Review Dependencies" en el módulo start. (Este paso es solo para revisar las dependencias; no agregarás ningún código).

start/build.gradle:

// TODO: Review Dependencies
// General Compose dependencies
implementation "androidx.activity:activity-compose:$activity_compose_version"
implementation "androidx.compose.ui:ui-tooling-preview:$compose_version"
implementation "androidx.compose.foundation:foundation:$compose_version"
implementation "androidx.compose.material:material-icons-extended:$compose_version"

// Compose for Wear OS Dependencies
implementation "androidx.wear.compose:compose-material:$wear_compose_version"

// Foundation is additive, so you can use the mobile version in your Wear OS app.
implementation "androidx.wear.compose:compose-foundation:$wear_compose_version"

Deberías reconocer muchas de las dependencias generales de Compose, por lo que no las abordaremos.

Pasemos a las dependencias de Wear OS.

Tal como se describió anteriormente, solo se incluye la versión específica de Wear OS de material (androidx.wear.compose:compose-material). Es decir, no verás ni incluirás androidx.compose.material:material en tu proyecto.

Es importante destacar que puedes usar otras bibliotecas de material con Wear Material. De hecho, lo hacemos en este codelab con androidx.compose.material:material-icons-extended.

Por último, incluimos la biblioteca de Wear foundation para Compose (androidx.wear.compose:compose-foundation). Como esto es adicional, puedes usarlo con el foundation que usas en dispositivos móviles. De hecho, es probable que ya hayas reconocido que lo incluimos en las dependencias generales de Compose.

Ahora que terminamos de analizar las dependencias, veamos la app principal.

4. Cómo consultar MainActivity

Haremos todo nuestro trabajo en el

start

módulo, así que asegúrate de que todos los archivos que abras estén allí.

Para comenzar, abre MainActivity en el módulo start.

Esta es una clase bastante simple que extiende ComponentActivity y usa setContent { WearApp() } para crear la IU.

A partir de tus conocimientos anteriores de Compose, esto debería resultarte conocido. Solo estamos configurando la IU.

Desplázate hacia abajo hasta la función que admite composición WearApp(). Antes de hablar sobre el código en sí, deberías ver un conjunto de las tareas pendientes diseminadas en todo el código. Cada una de ellas representa pasos en este codelab. Puedes ignorarlas por el momento.

Debería ser similar a lo siguiente:

Código en WearApp():

WearAppTheme {
    // TODO: Swap to ScalingLazyListState
    val listState = rememberLazyListState()

    /* *************************** Part 4: Wear OS Scaffold *************************** */
    // TODO (Start): Create a Scaffold (Wear Version)

        // Modifiers used by our Wear composables.
        val contentModifier = Modifier.fillMaxWidth().padding(bottom = 8.dp)
        val iconModifier = Modifier.size(24.dp).wrapContentSize(align = Alignment.Center)

        /* *************************** Part 3: ScalingLazyColumn *************************** */
        // TODO: Create a ScalingLazyColumn (Wear's version of LazyColumn)
        LazyColumn(
            modifier = Modifier.fillMaxSize(),
            contentPadding = PaddingValues(
                top = 32.dp,
                start = 8.dp,
                end = 8.dp,
                bottom = 32.dp
            ),
            verticalArrangement = Arrangement.Center,
            state = listState
        ) {

            // TODO: Remove item; for beginning only.
            item { StartOnlyTextComposables() }

            /* ******************* Part 1: Similar composables to Mobile ******************* */
            item { ButtonExample(contentModifier, iconModifier) }
            item { TextExample(contentModifier) }
            item { CardExample(contentModifier, iconModifier) }

            /* ********************* Part 2: Wear OS Only composables ********************* */
            item { ChipExample(contentModifier, iconModifier) }
            item { ToggleChipExample(contentModifier) }
        }

    // TODO (End): Create a Scaffold (Wear Version)

}

Para comenzar, configuramos el tema, WearAppTheme { }. Esto es exactamente lo mismo que escribes para dispositivos móviles; es decir, configuras un elemento MaterialTheme con colores, tipografía y formas.

Sin embargo, en el caso de Wear OS, generalmente recomendamos usar las formas predeterminadas de Material Wear, que están optimizadas para dispositivos redondos y no redondos, por lo que, si consultas nuestro theme/Theme.kt, verás que no anulamos las formas.

Si lo deseas, puedes abrir el theme/Theme.kt a fin de explorarlo con mayor profundidad, pero, nuevamente, es lo mismo que para dispositivos móviles.

A continuación, creamos algunos modificadores para los elementos de Wear que admiten composición que compilaremos, de modo que no debamos especificarlos cada vez. Se trata principalmente de centrar el contenido y agregar algo de relleno.

Luego, creamos un elemento LazyColumn que se usa a fin de producir una lista de desplazamiento vertical para un conjunto de elementos (al igual que los dispositivos móviles).

Código:

item { StartOnlyTextComposables() }

/* ******************* Part 1: Similar composables to Mobile ******************* */
item { ButtonExample(contentModifier, iconModifier) }
item { TextExample(contentModifier) }
item { CardExample(contentModifier, iconModifier) }

/* ********************* Part 2: Wear OS Only composables ********************* */
item { ChipExample(contentModifier, iconModifier) }
item { ToggleChipExample(contentModifier) }

Para los elementos en sí, solo StartOnlyTextComposables() produce cualquier IU. (Propagaremos el resto durante el codelab).

En realidad, estas funciones se encuentran en el archivo ReusableComponents.kt, que veremos en la siguiente sección.

Comencemos a usar Compose para Wear OS.

5. Cómo agregar elementos simples que admiten composición

Comenzaremos con tres elementos que admiten composición (Button, Text y Card) que probablemente ya conozcas.

Primero, quitaremos el elemento de Hello World que admite composición.

Busca "TODO: Remove item" y borra el comentario y la línea que aparece debajo:

Paso 1

// TODO: Remove item; for beginning only.
item { StartOnlyTextComposables() }

A continuación, agregaremos nuestro primer elemento que admite composición.

Cómo crear un elemento de botón que admite composición

Abre ReusableComponents.kt en el módulo start, busca "TODO: Create a Button Composable" y reemplaza el método actual que admite composición con este código.

Paso 2

// TODO: Create a Button Composable (with a Row to center)
@Composable
fun ButtonExample(
    modifier: Modifier = Modifier,
    iconModifier: Modifier = Modifier
) {
    Row(
        modifier = modifier,
        horizontalArrangement = Arrangement.Center
    ) {
        // Button
        Button(
            modifier = Modifier.size(ButtonDefaults.LargeButtonSize),
            onClick = { /* ... */ },
        ) {
            Icon(
                imageVector = Icons.Rounded.Phone,
                contentDescription = "triggers phone action",
                modifier = iconModifier
            )
        }
    }
}

La función que admite composición ButtonExample() (donde existe este código) ahora generará un botón centrado.

Veamos el código paso a paso.

El objeto Row solo se usa aquí para centrar el elemento Button que admite composición en la pantalla redonda. Para ver cómo lo hacemos, aplica el modificador que creamos en MainActivity y pásalo a esta función. Más adelante, cuando nos desplacemos por una pantalla circular, nos aseguraremos de que el contenido no esté cortado (por eso está centrado).

A continuación, crearemos el mismo elemento Button. El código es el mismo que usarías para un botón en un dispositivo móvil, pero, en nuestro caso, usamos ButtonDefault.LargeButtonSize. Estos son los tamaños optimizados para dispositivos Wear OS, así que asegúrate de usarlos.

Luego, configuramos el evento de clic en un archivo de lamba vacío. En nuestro caso, estos elementos que admiten composición son solo para una demostración, por lo que no los necesitaremos. Sin embargo, en una app real, nos comunicaremos con un ViewModel, por ejemplo, para realizar la lógica empresarial.

Luego, configuramos un ícono dentro de nuestro botón. Este código es el mismo que en un Icon anterior. Además, obtenemos el ícono de la biblioteca androidx.compose.material:material-icons-extended.

Por último, configuramos el modificador que establecimos anteriormente para los íconos.

Si ejecutas la app, deberías obtener algo similar a lo siguiente:

f9fce435c935d610.png

Este es el código que probablemente ya escribiste antes (lo que es genial). La diferencia es que ahora tienes un botón optimizado para Wear OS.

Muy sencillo. Veamos otra.

Cómo crear un elemento de texto que admite composición

En ReusableComponents.kt, busca "TODO: Create a Text Composable" y reemplaza el método que admite composición actual por este código.

Paso 3

// TODO: Create a Text Composable
@Composable
fun TextExample(modifier: Modifier = Modifier) {
    Text(
        modifier = modifier,
        textAlign = TextAlign.Center,
        color = MaterialTheme.colors.primary,
        text = stringResource(R.string.device_shape)
    )
}

Creamos el elemento Text que admite composición, configuramos su modificador, alineamos el texto, configuramos un color y, finalmente, configuramos el texto desde un recurso de strings.

Los desarrolladores de Compose deberían sentirse muy familiarizados con los elementos de texto que admiten composición, ya que el código es idéntico al de los dispositivos móviles.

Veamos cómo es:

52a4e318d12d7ba5.png

La función que admite composición TextExample() (donde colocamos nuestro código) ahora produce un elemento de texto que admite composición en nuestro color de material principal.

La string se extrae de nuestro archivo res/values/strings.xml. En realidad, si buscas en la carpeta res/values, deberías ver dos archivos strings.xml de recursos.

Wear OS proporciona recursos de strings para dispositivos redondos y no redondos, por lo que, si lo ejecutamos en un emulador cuadrado, la string cambiará:

27e50afef57b7717.png

Todo bien por ahora. Veamos nuestro último elemento similar que admite composición, Card.

Cómo crear un elemento de tarjeta que admite composición

En ReusableComponents.kt, busca "TODO: Create a Card" y reemplaza el método que admite composición actual con este código.

Paso 4

// TODO: Create a Card (specifically, an AppCard) Composable
@Composable
fun CardExample(
    modifier: Modifier = Modifier,
    iconModifier: Modifier = Modifier
) {
    AppCard(
        modifier = modifier,
        appImage = {
            Icon(
                imageVector = Icons.Rounded.Message,
                contentDescription = "triggers open message action",
                modifier = iconModifier
            )
        },
        appName = { Text("Messages") },
        time = { Text("12m") },
        title = { Text("Kim Green") },
        onClick = { /* ... */ }
    ) {
        Column(modifier = Modifier.fillMaxWidth()) {
            Text("On my way!")
        }
    }
}

Wear es un poco diferente, ya que tenemos dos tarjetas principales, AppCard y TitleCard.

En nuestro caso, queremos un Icon en nuestra tarjeta, por lo que usaremos AppCard (TitleCard se centra únicamente en el texto).

Creamos el elemento AppCard que admite composición, configuramos su modificador, agregamos un Icon y agregamos varios parámetros que admiten composición Text (cada uno para un espacio diferente en la tarjeta) y, por último, configuramos el texto del contenido principal al final.

Veamos cómo es:

dcb5e5bebf9f19d9.png

En este punto, puede que reconozcas que, para esos elementos que admiten composición, el código de Compose es prácticamente el mismo que el de un dispositivo móvil, lo que es genial. Puedes volver a usar todo ese conocimiento que ya adquiriste.

Muy bien. Veamos algunos elementos nuevos que admiten composición.

6. Cómo agregar elementos únicos de Wear que admiten composición

En esta sección, exploraremos los elementos que admiten composición Chip y ToggleChip.

Cómo crear un elemento de chip que admite composición

Los chips se especifican en los lineamientos de los materiales, pero no hay una función que admita composición en la biblioteca de material para dispositivos móviles.

Se diseñaron para ser una acción rápida con un toque, lo que resulta particularmente útil para un dispositivo Wear con espacio de pantalla limitado.

A continuación, se muestran algunas variaciones de la función que admite composición Chip para darte una idea de lo que puedes crear:

Escribamos algo de código.

En ReusableComponents.kt, busca "TODO: Create a Chip" y reemplaza el método que admite composición actual con este código.

Paso 5

// TODO: Create a Chip Composable
@Composable
fun ChipExample(
    modifier: Modifier = Modifier,
    iconModifier: Modifier = Modifier
) {
    Chip(
        modifier = modifier,
        onClick = { /* ... */ },
        label = {
            Text(
                text = "5 minute Meditation",
                maxLines = 1,
                overflow = TextOverflow.Ellipsis
            )
        },
        icon = {
            Icon(
                imageVector = Icons.Rounded.SelfImprovement,
                contentDescription = "triggers meditation action",
                modifier = iconModifier
            )
        },
    )
}

El elemento Chip que admite composición usa muchos de los mismos parámetros que utilizas con otros elementos que admiten composición (modificador y onClick), por lo que no es necesario revisarlos.

Además, toma una etiqueta (para la que creamos un elemento Text que admite composición) y un ícono.

El código Icon debería tener el mismo aspecto que el que viste en otros elementos que admiten composición, pero, para este, extraemos el ícono Self Improvement de la biblioteca androidx.compose.material:material-icons-extended.

Veamos cómo es (recuerda desplazarte hacia abajo):

77bde81f8f290f87.png

De acuerdo, veamos una variación en Toggle, el elemento ToggleChip que admite composición.

Cómo crear un elemento de ToggleChip que admite composición

ToggleChip es similar a un elemento Chip, pero permite que el usuario interactúe con un botón de selección, una tecla de activación o una casilla de verificación.

En ReusableComponents.kt, busca "TODO: Create a ToggleChip" y reemplaza el método que admite composición actual con este código.

Paso 6

// TODO: Create a ToggleChip Composable
@Composable
fun ToggleChipExample(modifier: Modifier = Modifier) {
    var checked by remember { mutableStateOf(true) }
    ToggleChip(
        modifier = modifier,
        checked = checked,
        toggleIcon = {
            ToggleChipDefaults.SwitchIcon(checked = checked)
        },
        onCheckedChange = {
            checked = it
        },
        label = {
            Text(
                text = "Sound",
                maxLines = 1,
                overflow = TextOverflow.Ellipsis
            )
        }
    )
}

Ahora, la función que admite composición ToggleChipExample() (donde existe este código) genera un ToggleChip mediante un botón de activación (en lugar de una casilla de verificación o un botón de selección).

Primero, creamos un MutableState. No hicimos esto en las otras funciones porque estamos realizando demostraciones de la IU para que puedas ver lo que ofrece Wear.

En una app normal, es probable que quieras pasar el estado activado y la lambda para procesar el toque, de modo que el elemento que admite composición no tenga estado (más información aquí).

En este caso, es más sencillo mostrar cómo funciona ToggleChip con un botón de activación en funcionamiento (aunque no hacemos nada con el estado).

Luego, configuramos el modificador, el estado activado y el ícono de activación para proporcionarnos el interruptor que deseamos. (En este caso, usamos los valores predeterminados).

Luego, creamos una expresión lambda para cambiar el estado y, por último, configuramos la etiqueta con un elemento Text que admite composición (y algunos parámetros básicos).

Veamos cómo es:

b76b501e91a64969.png

Ya viste muchos elementos específicos de Wear OS que admiten composición, y, como se indicó anteriormente, la mayor parte del código es casi la misma que la que escribes en dispositivos móviles.

Veamos algo un poco más avanzado.

7. Cómo migrar a ScalingLazyColumn

Es probable que hayas usado LazyColumn en tus apps para dispositivos móviles a fin de producir una lista de desplazamiento vertical.

Como los dispositivos redondos son más pequeños en las partes inferior y superior, hay menos espacio para mostrar elementos. Por lo tanto, Wear OS tiene su propia versión de LazyColumn para admitir mejor esos dispositivos redondos.

ScalingLazyColumn extiende LazyColumn a fin de admitir el escalamiento y la transparencia en la parte inferior y superior de la pantalla para que el usuario pueda leer más el contenido.

A continuación, te presentamos una demostración:

28460354eaf16eea.gif

Observa que, a medida que el elemento se acerca al centro, aumenta la escala a su tamaño original y, a medida que lo aleja, se vuelve a reducir (y se vuelve más transparente).

Aquí hay un ejemplo más concreto de una app:

307c969dccf58e49.gif

Descubrimos que esto realmente ayuda a mejorar la legibilidad.

Ahora que viste ScalingLazyListState en acción, comencemos a convertir nuestro LazyColumn.

Cómo convertir a ScalingLazyListState

En MainActivity.kt, busca el comentario "TODO: Swap to ScalingLazyListState" y reemplaza el comentario y la línea que aparecen a continuación con este código.

Paso 7

// TODO: Swap to ScalingLazyListState
val listState = rememberScalingLazyListState()

Los nombres son casi idénticos, menos la parte de "Escalamiento". Así como LazyListState controla el estado de un LazyColumn, ScalingLazyListState lo maneja por un ScalingLazyColumn.

Cómo convertir a ScalingLazyColumn.

A continuación, intercambiamos entre ScalingLazyColumn.

En MainActivity.kt, busca el comentario "TODO: Swap a ScalingLazyColumn" y reemplaza esa línea y la siguiente línea por este código.

Paso 8

        // TODO: Swap a ScalingLazyColumn (Wear's version of LazyColumn)
        ScalingLazyColumn(

Eso es todo. Veamos cómo es:

264ab059418a6526.png

Verás que se ajustan el contenido y la transparencia en la parte inferior y superior de la pantalla mientras te desplazas con muy poco trabajo para migrar.

Podrás notarlo con los elementos de meditación que admiten composición que se pueden mover hacia arriba y hacia abajo.

Ahora, llegamos al último tema: Scaffold de Wear OS.

8. Cómo agregar Scaffold

Scaffold proporciona una estructura de diseño a fin de ayudarte a organizar pantallas en patrones comunes, como los dispositivos móviles, pero en lugar de barras de aplicaciones, BAF, paneles laterales y otros elementos específicos para dispositivos móviles, admite tres diseños específicos de Wear con componentes de nivel superior: tiempo, viñeta y el indicador de desplazamiento/posición.

Además, controla dispositivos redondos y no redondos.

A continuación, te mostramos cómo se ven:

TimeText

Vignette

PositionIndicator

Examinaremos cada componente en detalle, pero primero vamos a poner a Scaffold en su lugar.

Cómo agregar Scaffold

Agreguemos el código estándar para Scaffold ahora.

Busca el comentario "TODO (Start): Create a Scaffold (Wear Version)" y agrega el siguiente código debajo.

Paso 9

// TODO (Start): Create a Scaffold (Wear Version)
Scaffold(
    timeText = { },
    vignette = { },
    positionIndicator = { }
) {

Explicaremos cada uno de estos parámetros en secuencia en pasos posteriores. En este momento, no estamos produciendo ninguna IU.

Luego, asegúrate de agregar el corchete de cierre en la ubicación correcta. Busca "TODO (End): Create a Scaffold (Wear Version)" y agrega el corchete allí:

Paso 10

// TODO (End): Create a Scaffold (Wear Version)
}

Ejecutémosla primero. Debería ver algo como esto:

2ddc667e07d8f04c.png

Notarás que, en realidad, no se comporta de la misma manera que antes desde que agregamos el objeto Scaffold, pero eso cambiará una vez que comencemos a implementar nuestros componentes.

Comencemos con el primero de los tres parámetros, TimeText.

TimeText

TimeText usa texto curvo de forma interna y les brinda a los desarrolladores una manera fácil de mostrar la hora sin colocar el elemento que admite composición ni realizar ningún trabajo con clases relacionadas con el tiempo.

Los lineamientos de Material requieren que muestres la hora en la parte superior de cualquier pantalla dentro de cualquier experiencia de superposición (o app). Este es un ejemplo de cómo debería verse:

29671ae0a7c3225b.png

Agregar TimeText es bastante simple.

Busca el comentario "timeText = { }," y reemplázalo por el siguiente código:

Paso 11

timeText = {
    if (!listState.isScrollInProgress) {
        TimeText()
    }
},

Agregamos un poco de lógica adicional para ocultar el tiempo si el usuario comienza a desplazarse.

Luego, creamos un elemento TimeText que admite composición. Podríamos agregar parámetros adicionales para añadir texto antes o después de la hora, pero queremos hacerlo más simple.

Intenta ejecutarla. Ahora deberías notar la hora, pero si te desplazas, desaparecerá.

896aaebb9a89bbe8.png

A continuación, analizaremos el Vignette.

Cómo agregar una viñeta

Una pantalla Vignette desenfoca los bordes inferior y superior de la pantalla de wearables cuando se muestra una pantalla que puede desplazarse.

Según el caso de uso, los desarrolladores pueden desenfocar la parte superior, la inferior o ambas.

Por ejemplo:

689ac8becaac6824.png

Solo tenemos una pantalla (que es una pantalla desplazable), por lo que queremos mostrar la viñeta para facilitar la legibilidad. Hagámoslo ahora.

Busca el comentario "vignette = { }," y reemplázalo por el siguiente código:

Paso 12

vignette = {
    // Only show a Vignette for scrollable screens. This code lab only has one screen,
    // which is scrollable, so we show it all the time.
    Vignette(vignettePosition = VignettePosition.TopAndBottom)
},

Lee el comentario para obtener más detalles sobre cuándo debe aparecer la viñeta y cuándo no. En nuestro caso, queremos que se muestre todo el tiempo y desenfocar la parte superior y la parte inferior de la pantalla.

9a91313e5d59f49e.png

Si observas la parte superior o la inferior (especialmente en los elementos púrpuras que admiten composición), deberías ver el efecto.

Para finalizar nuestro parámetro final de Scaffold, PositionIndicator

Cómo agregar PositionIndicator

El objeto PositionIndicator (también conocido como indicador de desplazamiento) es un indicador del lado derecho de la pantalla que muestra la ubicación del indicador actual según el tipo de objeto de estado que pases. En nuestro caso, será el ScalingLazyListState.

Por ejemplo:

181b19b55ce37251.png

Comencemos.

Si eres detallista, probablemente que hayas notado que elevamos el ScalingLazyListState sobre el Scaffold.

Es posible que te preguntes por qué se elevó allí cuando podría haber estado por encima de ScalingLazyColumn.

Debido a la curvatura de la pantalla, el indicador de posición debe estar centrado en el reloj, no solo en el viewport. De lo contrario, puede que se corte.

Por ejemplo, en la siguiente app, podemos suponer que el elemento "Playlist" que admite composición no forma parte del área desplazable:

c9f96a90a3e811fb.png

Si el indicador de posición no estuviera centrado en la pantalla (como está aquí), sino que estuviera centrado en el puerto de visualización de la lista, en su mayoría estaría cortado debido a la pantalla redonda. Es decir, no hay ninguna pantalla allí.

Ahora que ya analizamos por qué se perfeccionaron esos niveles, vamos a agregarlo a la app.

Busca el comentario "positionIndicator = { }" y reemplázalo por el siguiente código:

Paso 12

positionIndicator = {
    PositionIndicator(
        scalingLazyListState = listState
    )
}

Es bastante sencillo: PositionIndicator requiere que el estado de desplazamiento se procese correctamente y ahora puede hacerlo.

Además, tiene una linda función que se oculta cuando el usuario no se desplaza por la página.

Estamos usando ScalingLazyListState, pero PositionIndicator toma muchas otras opciones de desplazamiento, p. ej., ScrollState y LazyListState, e incluso pueden controlar el botón lateral giratorio o

el bisel que gira. Para ver todas las opciones, consulta los KDocs de cada versión.

Ahora veamos cómo se ve esto:

8c278b78ab008cbb.png

Intenta desplazarlo hacia arriba y hacia abajo. El indicador de desplazamiento solo debería aparecer cuando te desplazas.

Buen trabajo. Terminaste una demostración de la IU de la mayoría de los elementos que admiten composición de Wear OS.

9. Felicitaciones

¡Felicitaciones! Ya aprendiste los conceptos básicos del uso de Compose en Wear OS.

Ahora puedes volver a aplicar todo tu conocimiento desde el dispositivo móvil y comenzar a crear apps atractivas para Wear OS.

¿Qué sigue?

Consulta los otros codelabs de Wear OS:

Lecturas adicionales