Coordina tu IU con la barra de estado del sistema

Hasta Wear OS 7 (API 37), la plataforma no renderizaba una barra de estado del sistema sobre las ventanas de la aplicación. Las apps eran propietarias de toda la pantalla y podían dibujar cualquier contenido en la parte superior (posición de las 12 en punto), como un reloj TimeText integrado en la app, encabezados curvos personalizados o controles superiores.

A partir de Wear OS 8, y ya disponible para pruebas de versión preliminar anticipada en el emulador de versión preliminar de Wear OS 7.1 (API 37.2-beta1), el sistema renderiza una barra de estado sobre las ventanas de la aplicación en la posición de las 12 en punto para mostrar la hora y los indicadores de estado. Para evitar la superposición con la barra de estado del sistema, las apps deben dejar de renderizar su propio reloj (TimeText) y respetar las inserciones de la ventana de la barra de estado superior (que se controlan automáticamente con AppScaffold y ScreenScaffold a partir de Wear Compose 1.8) o bien ocultar la barra de estado del sistema cuando se necesite una experiencia envolvente de pantalla completa.

Barra de estado del sistema en Wear OS 8
Figura 1: Barra de estado del sistema en Wear OS 8.

Estos son algunos de los beneficios clave:

  • Coherencia visual: Una tipografía, una ubicación y una placa posterior uniformes para el reloj en todo el sistema y en todas las apps.
  • Indicadores de estado del sistema: Permite que la plataforma muestre íconos de estado (como indicadores de ubicación y micrófono activos, estado de conectividad o información de la batería) y la hora en todas las plataformas. Solo se muestra un ícono a la vez, según la prioridad.
  • Coordinación automática de desplazamiento y transición: Cuando se vincula con Jetpack Compose para Wear OS 1.8, la barra de estado del sistema se oculta automáticamente cuando los usuarios se desplazan por el contenido y vuelve a aparecer después de un breve retraso de inactividad (2 s).

Configura la app

Para comenzar, completa los siguientes pasos de requisitos previos:

  1. Instala la versión preliminar de Android Studio (Canary).
  2. En SDK Manager, descarga la imagen del sistema del emulador de la versión preliminar de Wear OS 7.1 (API 37.2-beta1). Esta versión proporciona acceso anticipado a la barra de estado del sistema de Wear OS 8 antes del SDK de Wear OS 8.
  3. En el Administrador de dispositivos, crea e inicia un dispositivo virtual de Wear OS con la imagen de la API 37.2-beta1.

Para admitir la barra de estado del sistema en tu app, actualiza la versión de targetSdk de tu app a la 35 o una posterior. La plataforma solo activa la barra de estado del sistema para las apps que se orientan a la API 35 y versiones posteriores para preservar la retrocompatibilidad con las apps heredadas. Además, actualiza tus dependencias de Compose para Wear a la versión alfa más reciente (actualmente, 1.8.0-alpha02), como se muestra en el siguiente fragmento de código. Si tu app usa una versión anterior de Wear Compose, puedes usar la habilidad de migración de Wear Compose Material 3 para facilitar la migración.

android {
    defaultConfig {
        targetSdk = 35
    }
}

dependencies {
    implementation("androidx.wear.compose:compose-foundation:1.8.0-alpha02")
    implementation("androidx.wear.compose:compose-material3:1.8.0-alpha02")
}

Usa la barra de estado del sistema

En la versión alfa más reciente de Wear Compose Material 3 1.8.0 (actualmente, 1.8.0-alpha02), la biblioteca habilita automáticamente tu app combinando la propiedad com.google.wear.ENABLE_GLOBAL_STATUS_BAR <meta-data> en tu AndroidManifest.xml. En el tiempo de ejecución, AppScaffold y ScreenScaffold verifican si la barra de estado del sistema está habilitada en el dispositivo y si esta propiedad de habilitación del manifiesto está configurada como true:

  • En el emulador de versión preliminar o Wear OS 8 y versiones posteriores (cuando se habilita): AppScaffold suprime su TimeText interno para que la barra de estado del sistema se renderice de forma limpia en la posición de las 12 en punto sin duplicación. ScreenScaffold vuelve a calcular contentPadding para tener en cuenta los límites de inserción de la barra de estado y coordina la ocultación y la visualización de la barra de estado a medida que se desplaza la lista.
  • En Wear OS 7 y dispositivos anteriores (o cuando no se habilita): AppScaffold recurre automáticamente a renderizar el TimeText estándar integrado en la app, lo que mantiene la retrocompatibilidad total desde una sola base de código.
@Composable
fun GsbSampleApp() {
    // AppScaffold coordinates the system status bar across the app
    // and falls back to rendering TimeText on Wear OS 7 and earlier.
    AppScaffold {
        val columnState = rememberTransformingLazyColumnState()

        // ScreenScaffold includes status bar top inset clearance in
        // contentPadding and hides/shows the status bar during list scrolling.
        ScreenScaffold(scrollState = columnState) { contentPadding ->
            TransformingLazyColumn(
                state = columnState,
                contentPadding = contentPadding,
            ) {
                item {
                    ListHeader { Text("Hello Status Bar") }
                }
                items(count = 15) { index ->
                    Button(onClick = { /* Handle click */ }) {
                        Text("Item #${index + 1}")
                    }
                }
            }
        }
    }
}

Esto es lo que puedes esperar cuando ejecutes la muestra:

  • En reposo (parte superior de la lista): La barra de estado del sistema se muestra en la posición de las 12 en punto. El encabezado "Hello Status Bar" se encuentra debajo del área de inserción de la barra de estado sin recortarse ni superponerse.
  • Desplazamiento hacia abajo: A medida que te desplazas por los elementos de la lista, la barra de estado se oculta y los elementos de la lista se desplazan de borde a borde detrás del bisel superior.
  • Inactiva: Cuando dejas de desplazarte y sueltas la pantalla, la barra de estado vuelve a aparecer automáticamente después de ~2 segundos.

Cómo controlar situaciones y personalizaciones comunes

En las siguientes secciones, se describe cómo controlar situaciones comunes que puedes encontrar cuando trabajas con la barra de estado del sistema.

Cómo controlar pantallas estáticas (sin desplazamiento)

En las pantallas que usan un diseño estático (como Column o Box) en lugar de una lista de desplazamiento, aplica el contentPadding que proporciona ScreenScaffold a tu diseño raíz para que los elementos de la IU superiores no se superpongan con la barra de estado del sistema:

AppScaffold {
    ScreenScaffold { contentPadding ->
        Column(modifier = Modifier.padding(contentPadding)) {
            Text("Static Screen Content")
        }
    }
}

Cómo trabajar con componentes interactivos de pantalla completa

Los componentes interactivos de pantalla completa en Wear Compose Material 3, incluidos AlertDialog, Dialog, Stepper, TimePicker y DatePicker, ocultan automáticamente la barra de estado del sistema mientras están en pantalla para que sus controles tengan acceso completo a la parte superior de la pantalla circular. Cuando se descarta, la barra de estado del sistema se restablece automáticamente con la API del controlador de inserciones de ventanas.

Cambiar al modo envolvente

Para cambiar al modo envolvente, en el que se ocultan la barra de estado del sistema y la TimeText local, agrega el elemento de componibilidad StatusBarSuppression a tu app o pantalla. Reserva el modo envolvente para las pantallas que el usuario ve brevemente (superposiciones de confirmación, diálogos) o que usan toda la pantalla (indicadores de progreso de pantalla completa).

Cuándo usar el modo envolvente a nivel de la pantalla

Si solo una pantalla específica de tu app debe ser de pantalla completa o envolvente, llama a StatusBarSuppression() dentro del contenido de ScreenScaffold. ScreenScaffold oculta automáticamente la barra de estado del sistema (y omite el padding de inserción de la barra de estado superior) mientras esa pantalla está activa y, luego, restablece la barra de estado del sistema cuando se vuelve a otras pantallas:

AppScaffold {
    ScreenScaffold() {
        StatusBarSuppression()
        // Full-screen immersive content
    }
}

Considera cuándo usar el modo envolvente a nivel de la app

Si toda tu aplicación (o Activity) es una experiencia envolvente de pantalla completa en todas las pantallas, usa StatusBarSuppression en el nivel AppScaffold y une tu contenido para suprimir la barra de estado del sistema en todas las pantallas:

// Use StatusBarSuppression at AppScaffold level and wrap your content
// to suppress status bar in the entire scaffold.
AppScaffold {
    StatusBarSuppression {
        SwipeDismissableNavHost(...) {
            // Nested screens inherit suppression and 0.dp padding
        }
    }
}

Anulaciones de texto de hora personalizadas de Display

Si necesitas mostrar un encabezado curvo personalizado o inhabilitar temporalmente la barra de estado del sistema en una pantalla específica o en toda la app durante la migración para Wear OS 8, pasar un elemento timeText componible personalizado suprime la barra de estado del sistema:

// Screen-level custom TimeText override:
ScreenScaffold(
    timeText = { TimeText { timeTextCurvedText("Custom Status") } },
) {
    // Content
}

// App-level opt-out using in-app TimeText:
AppScaffold(
    timeText = { TimeText() },
) {
    // Screens
}

Implementación con vistas (no recomendado)

Si tu app usa vistas de Android en lugar de Jetpack Compose para Wear OS, habilita la función con AndroidManifest.xml. A diferencia de la versión alfa más reciente de Wear Compose Material 3, que habilita la barra de estado del sistema automáticamente, las apps basadas en objetos View deben habilitar la opción de forma explícita agregando la etiqueta ENABLE_GLOBAL_STATUS_BAR <meta-data> dentro de <application>:

<application ...>
    <meta-data
        android:name="com.google.wear.ENABLE_GLOBAL_STATUS_BAR"
        android:value="true" />
</application>

Supervisa las inserciones de la ventana superior

Usa ViewCompat.setOnApplyWindowInsetsListener y verifica el valor de windowInsets.getInsets(WindowInsetsCompat.Type.statusBars()). Cuando statusBarInsets.top > 0, quita la IU heredada de las 12 en punto y ajusta el padding superior; de lo contrario, recurre a la IU heredada:

ViewCompat.setOnApplyWindowInsetsListener(rootView) { view, windowInsets ->
    val statusBarInsets = windowInsets.getInsets(
        WindowInsetsCompat.Type.statusBars()
    )

    if (statusBarInsets.top > 0) {
        // status bar is visible: remove legacy 12 o'clock UI and apply top inset padding
        view.updatePadding(top = statusBarInsets.top)
    } else {
        // status bar is not visible: fall back to legacy UI and padding
    }

    WindowInsetsCompat.CONSUMED
}

Oculta y muestra la barra de estado de manera programática

A diferencia de ScreenScaffold en Compose, las apps basadas en View deben ocultar o mostrar explícitamente la barra de estado del sistema (por ejemplo, cuando se ingresa a una vista envolvente de pantalla completa o se coordina el comportamiento de desplazamiento) con WindowInsetsControllerCompat:

val insetsController = WindowCompat.getInsetsController(window, window.decorView)

// Hide the status bar
insetsController.hide(WindowInsetsCompat.Type.statusBars())

// Show the status bar
insetsController.show(WindowInsetsCompat.Type.statusBars())

Prueba tu app

Cuando pruebes tu app en el emulador de la versión preliminar de la versión beta de Wear OS 7.1 (API 37.2-beta1), verifica lo siguiente:

  • El reloj aparece solo una vez: Verifica que solo aparezca la hora de la barra de estado del sistema en la posición de las 12 en punto y que no se superpongan el TimeText heredado de la app ni el contenido de la app.
  • Padding superior: Verifica que los títulos de la pantalla, los encabezados y los botones superiores aparezcan debajo de la barra de estado.
  • Superposiciones y diálogos de pantalla completa: Verifica que los diálogos, los selectores, los pasos y las actividades personalizadas de pantalla completa oculten la barra de estado cuando se abran y que la restablezcan cuando se cierren.