Mengoordinasikan UI Anda dengan status bar sistem

Hingga Wear OS 7 (API 37), platform tidak merender status bar sistem di atas jendela aplikasi—aplikasi memiliki seluruh layar dan dapat menggambar konten apa pun di posisi atas (pukul 12) (seperti jam TimeText dalam aplikasi, header melengkung kustom, atau kontrol atas).

Mulai Wear OS 8—dan kini tersedia untuk pengujian pratinjau awal di Emulator Pratinjau Beta Wear OS 7.1 (API 37.2-beta1)—sistem merender status bar di atas jendela aplikasi pada posisi jam 12 untuk menampilkan indikator waktu dan status. Untuk mencegah tumpang-tindih dengan status bar sistem, aplikasi harus berhenti merender jamnya sendiri (TimeText) dan mengikuti inset jendela status bar atas (ditangani secara otomatis oleh AppScaffold dan ScreenScaffold dari Wear Compose 1.8 dan yang lebih baru), atau menyembunyikan status bar sistem saat pengalaman imersif layar penuh diperlukan.

Status bar sistem di Wear OS 8
Gambar 1. Status bar sistem di Wear OS 8.

Manfaat utamanya meliputi:

  • Konsistensi visual: tipografi, penempatan, dan pelat belakang jam yang seragam di seluruh sistem dan semua aplikasi.
  • Indikator status sistem: memungkinkan platform menampilkan ikon status (seperti indikator mikrofon dan lokasi aktif, status konektivitas, atau informasi baterai) dan waktu di seluruh platform. Hanya satu ikon yang ditampilkan dalam satu waktu, berdasarkan prioritas.
  • Koordinasi scroll & transisi otomatis: jika disambungkan dengan Jetpack Compose untuk Wear OS 1.8, status bar sistem akan otomatis disembunyikan saat pengguna men-scroll konten dan muncul kembali setelah jeda tidak ada aktivitas singkat (2 dtk).

Menyiapkan aplikasi

Untuk memulai, selesaikan langkah-langkah prasyarat berikut:

  1. Instal Pratinjau Android Studio (Canary).
  2. Di SDK Manager, download Image Sistem Emulator Pratinjau Wear OS 7.1 (API 37.2-beta1). Versi ini memberikan akses awal ke status bar sistem Wear OS 8 sebelum SDK Wear OS 8.
  3. Di Pengelola Perangkat, buat dan luncurkan perangkat virtual Wear OS menggunakan image API 37.2-beta1.

Untuk mendukung status bar sistem di aplikasi Anda, update versi targetSdk aplikasi Anda ke 35 atau yang lebih tinggi. Platform hanya mengaktifkan status bar sistem untuk aplikasi yang menargetkan API 35+ guna mempertahankan kompatibilitas mundur untuk aplikasi lama. Selain itu, update dependensi Wear Compose ke versi alfa terbaru—saat ini 1.8.0-alpha02—seperti yang ditunjukkan dalam cuplikan kode berikut. Jika aplikasi Anda menggunakan Wear Compose versi lama, Anda dapat menggunakan kemampuan migrasi Wear Compose Material 3 untuk memfasilitasi migrasi.

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")
}

Menggunakan status bar sistem

Dalam versi alfa terbaru Wear Compose Material 3 1.8.0—saat ini 1.8.0-alpha02—library akan otomatis mengikutsertakan aplikasi Anda dengan menggabungkan properti com.google.wear.ENABLE_GLOBAL_STATUS_BAR <meta-data> ke dalam AndroidManifest.xml. Pada runtime, AppScaffold dan ScreenScaffold memeriksa apakah status bar sistem diaktifkan di perangkat dan apakah properti keikutsertaan manifes ini ditetapkan ke true:

  • Di emulator pratinjau/Wear OS 8+ (jika diaktifkan): AppScaffold menonaktifkan TimeText internalnya sehingga status bar sistem dirender dengan rapi di posisi jam 12 tanpa duplikasi. ScreenScaffold menghitung ulang contentPadding untuk memperhitungkan batas inset Status Bar dan mengoordinasikan penyembunyian dan penampilan status bar saat daftar di-scroll.
  • Di Wear OS 7 dan perangkat yang lebih lama (atau jika tidak diaktifkan): AppScaffold akan otomatis kembali merender TimeText dalam aplikasi standar, sehingga mempertahankan kompatibilitas mundur penuh dari satu codebase.
@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}")
                    }
                }
            }
        }
    }
}

Berikut yang akan terjadi saat menjalankan contoh:

  • Saat tidak aktif (atas daftar): status bar sistem ditampilkan di posisi jam 12. Header "Hello Status Bar" berada di bawah area inset status bar tanpa terpotong atau tumpang-tindih.
  • Men-scroll ke bawah: saat Anda men-scroll item daftar, status bar akan disembunyikan, dan item daftar akan di-scroll dari tepi ke tepi di belakang bezel atas.
  • Tidak ada aktivitas: saat Anda berhenti men-scroll dan melepaskan layar, status bar akan otomatis muncul kembali setelah sekitar 2 detik.

Menangani skenario dan penyesuaian umum

Bagian berikut menjelaskan cara menangani skenario umum yang mungkin Anda alami saat menggunakan status bar sistem.

Menangani layar yang tidak dapat di-scroll (statis)

Pada layar yang menggunakan tata letak statis (seperti Column atau Box), bukan daftar scroll, terapkan contentPadding yang disediakan oleh ScreenScaffold ke tata letak root agar elemen UI teratas tidak tumpang-tindih dengan status bar sistem:

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

Menggunakan komponen interaktif layar penuh

Komponen interaktif layar penuh di Wear Compose Material 3—termasuk AlertDialog, Dialog, Stepper, TimePicker, dan DatePicker—otomatis menyembunyikan status bar sistem saat berada di layar sehingga kontrolnya memiliki akses penuh ke bagian atas layar melingkar. Saat ditutup, status bar sistem akan otomatis dipulihkan menggunakan API pengontrol inset jendela.

Beralih ke mode imersif

Untuk beralih ke mode imersif—tempat status bar sistem dan TimeText lokal disembunyikan—tambahkan composable StatusBarSuppression ke aplikasi atau layar Anda. Cadangkan mode imersif untuk layar yang dilihat pengguna secara singkat (overlay konfirmasi, dialog) atau yang menggunakan seluruh layar (indikator progres layar penuh).

Mempertimbangkan kapan harus menggunakan mode imersif tingkat layar

Jika hanya layar tertentu di aplikasi Anda yang harus dalam mode layar penuh/imersif, panggil StatusBarSuppression() dalam konten ScreenScaffold. ScreenScaffold otomatis menyembunyikan status bar sistem (dan menghilangkan padding inset status bar atas) saat layar tersebut aktif, lalu memulihkan status bar sistem saat kembali ke layar lain:

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

Mempertimbangkan kapan harus menggunakan mode imersif tingkat aplikasi

Jika seluruh aplikasi (atau Activity) Anda adalah pengalaman layar penuh yang imersif di semua layar, gunakan StatusBarSuppression di tingkat AppScaffold dan gabungkan konten Anda untuk menyembunyikan status bar sistem di semua layar:

// 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
        }
    }
}

Menampilkan penggantian teks waktu kustom

Jika Anda perlu menampilkan header melengkung kustom atau memilih tidak menggunakan status bar sistem untuk sementara di layar tertentu atau di seluruh aplikasi selama migrasi untuk Wear OS 8, meneruskan composable timeText kustom akan menyembunyikan status bar sistem:

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

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

Menerapkan menggunakan Tampilan (tidak direkomendasikan)

Jika aplikasi Anda menggunakan View Android, bukan Jetpack Compose untuk Wear OS, pilih ikut serta menggunakan AndroidManifest.xml. Tidak seperti rilis alfa terbaru Wear Compose Material 3, yang mengaktifkan status bar sistem secara otomatis, aplikasi berbasis View harus diikutsertakan secara eksplisit dengan menambahkan tag ENABLE_GLOBAL_STATUS_BAR <meta-data> di dalam <application>:

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

Memantau inset jendela atas

Gunakan ViewCompat.setOnApplyWindowInsetsListener dan periksa nilai windowInsets.getInsets(WindowInsetsCompat.Type.statusBars()). Jika statusBarInsets.top > 0, hapus UI jam 12 lama dan sesuaikan padding atas; jika tidak, kembali ke UI lama:

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
}

Menyembunyikan dan menampilkan status bar secara terprogram

Tidak seperti ScreenScaffold di Compose, aplikasi berbasis View harus secara eksplisit menyembunyikan atau menampilkan status bar sistem (misalnya, saat memasuki tampilan imersif layar penuh atau mengoordinasikan perilaku scroll-away) menggunakan 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())

Menguji aplikasi

Saat menguji aplikasi di Emulator Pratinjau Wear OS 7.1 Beta (API 37.2-beta1), periksa hal berikut:

  • Jam hanya muncul sekali: Pastikan hanya waktu status bar sistem yang muncul di posisi jam 12 dan tidak ada TimeText dalam aplikasi lama dan konten aplikasi yang tumpang-tindih dengannya.
  • Padding atas: Pastikan judul layar, header, dan tombol atas muncul di bawah status bar.
  • Overlay & dialog layar penuh: Pastikan dialog, pemilih, stepper, dan aktivitas layar penuh kustom menyembunyikan status bar saat dibuka, dan memulihkannya saat ditutup.