Melihat pratinjau UI Anda di Compose untuk Wear OS

Pratinjau Compose Android Studio memungkinkan Anda memeriksa dan memverifikasi composable Wear OS di berbagai ukuran tampilan smartwatch, bezel bulat, dan skala font langsung di IDE—tanpa men-deploy aplikasi ke smartwatch fisik atau emulator.

Karena perangkat Wear OS menampilkan layar melingkar yang memotong konten di sudutnya dan overlay sistem seperti TimeText dan ScrollIndicator melengkung di sepanjang tepi layar, mengonfigurasi pratinjau khusus untuk Wear OS sangat penting untuk mendeteksi masalah tata letak sejak awal.


Menyiapkan dependensi pratinjau

Untuk menggunakan anotasi pratinjau dan definisi perangkat Compose Wear OS, tambahkan dependensi berikut ke file build.gradle.kts modul Anda:

dependencies {
    // Provides @WearPreview* multipreview annotations
    // (such as @WearPreviewDevices and @WearPreviewFontScales)
    implementation("androidx.wear.compose:compose-ui-tooling:1.7.0")

    // Provides WearDevices constants
    // (such as WearDevices.SMALL_ROUND and WearDevices.LARGE_ROUND)
    implementation("androidx.wear:wear-tooling-preview:1.0.0")

    // Standard Compose preview support and interactive/animation inspection
    implementation("androidx.compose.ui:ui-tooling-preview")
    debugImplementation("androidx.compose.ui:ui-tooling")
}

Pilih yang akan dilihat pratinjaunya: layar versus komponen

Cara Anda mengonfigurasi pratinjau bergantung pada apakah Anda melihat pratinjau layar penuh atau komponen UI terisolasi.

Melihat pratinjau layar penuh (AppScaffold + ScreenScaffold)

Saat melihat pratinjau seluruh layar, selalu bungkus composable layar Anda dalam AppScaffold dan ScreenScaffold menggunakan anotasi pratinjau perangkat Wear. Hal ini merender tampilan jam melingkar dan memastikan bahwa:

  • TimeText dirender di tepi melengkung atas tampilan jam.
  • ScrollIndicator muncul di sepanjang bezel kanan.
  • EdgeButton diposisikan dengan benar dan dipangkas di kurva bawah.
  • Padding konten dan kliping layar melingkar mencerminkan hardware jam tangan pintar secara akurat.
@WearPreviewDevices
@Composable
fun WorkoutScreenPreview() {
    MaterialTheme {
        // AppScaffold provides the top-level TimeText overlay
        AppScaffold {
            // WorkoutScreen contains its own ScreenScaffold and content
            WorkoutScreen(
                heartRate = 142,
                elapsedTime = "12:45"
            )
        }
    }
}
WorkoutScreenPreview dirender di WearDevices.SMALL_ROUND

Lingkaran Kecil (192x192 dp)

WorkoutScreenPreview dirender di WearDevices.LARGE_ROUND

Lingkaran Besar (227x227 dp)

Melihat pratinjau komponen terisolasi

Saat melihat pratinjau setiap komponen—seperti Card, Button, atau chip status kustom—hilangkan parameter device dan gunakan @Preview standar dengan latar belakang gelap. Hal ini memastikan bahwa warna dan kontras Material 3 Wear ditampilkan secara akurat tanpa merender tampilan jam melingkar penuh:

@Preview(
    showBackground = true,
    backgroundColor = 0xFF000000
)
@Composable
fun HeartRateCardPreview() {
    MaterialTheme {
        HeartRateCard(bpm = 142, zone = "Aerobic")
    }
}
Pratinjau komponen terisolasi HeartRateCardPreview tanpa bingkai smartwatch

Pratinjau komponen terisolasi (tanpa bingkai perangkat).


Anotasi multipratinjau bawaan

Paket androidx.wear.compose.ui.tooling.preview menyediakan anotasi bawaan yang secara otomatis mengonfigurasi latar belakang gelap (backgroundColor = 0xFF000000, showBackground = true) dan dimensi perangkat smartwatch melingkar:

Annotation Yang dirender Kapan digunakan
@WearPreviewSmallRound 1 pratinjau di WearDevices.SMALL_ROUND (192x192 dp). Iterasi cepat pada ukuran tampilan melingkar yang paling terbatas.
@WearPreviewLargeRound 1 pratinjau di WearDevices.LARGE_ROUND (227x227 dp). Memeriksa kepadatan tata letak dan ruang ekstra pada smartwatch yang lebih besar.
@WearPreviewDevices 2 pratinjau: SMALL_ROUND dan LARGE_ROUND. Pemeriksaan multiperangkat standar untuk setiap composable layar.
@WearPreviewFontScales 6 pratinjau di SMALL_ROUND di semua skala font Wear: Kecil (0.94f), Normal (1.0f), Sedang (1.06f), Besar (1.12f), Lebih Besar (1.18f), dan Terbesar (1.24f). Memeriksa pelengkapan teks, elipsis, dan perluasan tinggi tombol.

Anda dapat menumpuk @WearPreviewDevices dan @WearPreviewFontScales pada fungsi pratinjau yang sama untuk membuat matriks uji yang komprehensif:

@WearPreviewDevices
@WearPreviewFontScales
@Composable
fun MessageDetailScreenPreview() {
    MaterialTheme {
        AppScaffold {
            MessageDetailScreen(
                sender = "Alex",
                body = "Running 5 mins late!"
            )
        }
    }
}

Anotasi pratinjau kustom dan spesifikasi hardware

Jika Anda memerlukan kontrol yang lebih baik—seperti menguji dimensi hardware tertentu, string yang dilokalkan panjang, atau kombinasi kasus terburuk—Anda dapat mengonfigurasi @Preview secara langsung atau menentukan anotasi multi-pratinjau kustom Anda sendiri.

Konstanta WearDevices yang tersedia dan spesifikasi hardware kustom

Objek androidx.wear.tooling.preview.devices.WearDevices menyediakan ID perangkat standar:

  • WearDevices.SMALL_ROUND ("id:wearos_small_round", 192x192dp)
  • WearDevices.LARGE_ROUND ("id:wearos_large_round", 227x227dp)

Untuk melihat pratinjau pada layar bulat ekstra besar (seperti smartwatch 44 mm–45 mm atau model Ultra pada 240x240 dp), teruskan string spec: kustom ke parameter device:

@Preview(
    name = "XL Round Watch (240dp)",
    device = "spec:width=240dp,height=240dp,dpi=320,isRound=true",
    showBackground = true,
    backgroundColor = 0xFF000000
)
@Composable
fun WorkoutScreenXlPreview() {
    MaterialTheme {
        AppScaffold {
            WorkoutScreen(heartRate = 142, elapsedTime = "12:45")
        }
    }
}

Membuat anotasi multi-pratinjau kustom

Untuk memeriksa skenario ekstrem, buat anotasi multi-pratinjau kustom yang menyandingkan layar bulat terkecil dengan skala font terbesar dan lokalitas verbose (seperti Jerman) bersama layar bulat besar standar:

@Preview(
    name = "1. Standard Large Round",
    group = "Layout extremes",
    device = WearDevices.LARGE_ROUND,
    backgroundColor = 0xFF000000,
    showBackground = true
)
@Preview(
    name = "2. Extreme Small Round (Largest Font + German)",
    group = "Layout extremes",
    device = WearDevices.SMALL_ROUND,
    fontScale = 1.24f,
    locale = "de-rDE",
    backgroundColor = 0xFF000000,
    showBackground = true
)
annotation class WearPreviewExtremes
Pratinjau Bulat Besar Standar

1. Standard Large Round

Bulat Sangat Kecil dengan skala font Terbesar

2. Lingkaran Sangat Kecil (Font Terbesar + Jerman)


Melihat pratinjau kolom yang dapat di-scroll (TransformingLazyColumn)

Secara default, TransformingLazyColumn diinisialisasi dengan item pertamanya (index = 0) yang disematkan ke bagian atas layar. Namun, di Wear OS, item mengubah tinggi dan sudut bulatnya (SurfaceTransformation) saat mendekati tepi melengkung atas dan bawah layar, dan EdgeButton hanya muncul saat di-scroll ke bawah.

Untuk melihat pratinjau tampilan daftar Anda saat di-scroll sebagian ke bawah atau di bagian bawah daftar:

Langkah 1: Angkat TransformingLazyColumnState di composable layar Anda

Izinkan composable layar Anda menerima parameter TransformingLazyColumnState dengan rememberTransformingLazyColumnState() sebagai nilai default:

@Composable
fun InboxScreen(
    messages: List<Message>,
    columnState: TransformingLazyColumnState = rememberTransformingLazyColumnState(),
) {
    val transformationSpec = rememberTransformationSpec()

    ScreenScaffold(
        scrollState = columnState,
        edgeButton = {
            EdgeButton(onClick = { /* Compose new */ }) {
                Text("New message")
            }
        }
    ) { contentPadding ->
        TransformingLazyColumn(
            state = columnState,
            contentPadding = contentPadding,
        ) {
            items(messages.size) { index ->
                Card(
                    onClick = {},
                    modifier = Modifier
                        .fillMaxWidth()
                        .transformedHeight(this, transformationSpec)
                        .minimumVerticalContentPadding(
                            CardDefaults.minimumVerticalListContentPadding
                        ),
                    transformation = SurfaceTransformation(transformationSpec),
                ) {
                    Text(messages[index].subject)
                }
            }
        }
    }
}

Langkah 2: Teruskan initialAnchorItemIndex di @Preview Anda

rememberTransformingLazyColumnState menerima dua parameter scroll awal opsional:

  • initialAnchorItemIndex: Int: Jika disetel ke indeks non-negatif (misalnya, 3), daftar akan diinisialisasi dengan item tersebut ditengahkan di viewport smartwatch.
  • initialAnchorItemScrollOffset: Int: Offset piksel opsional yang diterapkan relatif terhadap item anchor yang berada di tengah.

Anda dapat membuat pratinjau berdampingan yang menampilkan status Atas, Tengah (di-scroll), dan Bawah (EdgeButton terlihat) dari layar yang sama persis:

@WearPreviewLargeRound
@Composable
fun InboxScreenTopPreview() {
    MaterialTheme {
        AppScaffold {
            // Default (-1): Pinned to top of list (index 0)
            InboxScreen(messages = sampleMessages)
        }
    }
}

@WearPreviewLargeRound
@Composable
fun InboxScreenScrolledMiddlePreview() {
    MaterialTheme {
        AppScaffold {
            // Centers item index 3 in the viewport, showing top/bottom item morphing
            InboxScreen(
                messages = sampleMessages,
                columnState = rememberTransformingLazyColumnState(
                    initialAnchorItemIndex = 3
                )
            )
        }
    }
}

@WearPreviewLargeRound
@Composable
fun InboxScreenBottomEdgeButtonPreview() {
    MaterialTheme {
        AppScaffold {
            // Anchors on the last item so the EdgeButton is visible at the bottom
            InboxScreen(
                messages = sampleMessages,
                columnState = rememberTransformingLazyColumnState(
                    initialAnchorItemIndex = sampleMessages.lastIndex
                )
            )
        }
    }
}
InboxScreen disematkan ke bagian atas daftar

Atas (Default -1)

InboxScreen di-scroll ke indeks tengah 3

Tengah (initialAnchorItemIndex = 3)

InboxScreen di-scroll ke bawah dengan EdgeButton yang diluaskan

Bawah (EdgeButton diperluas)

Tips: Anda juga dapat mengklik Mulai Mode Interaktif pada @Preview mana pun di Android Studio untuk men-scroll TransformingLazyColumn secara langsung dengan mouse atau trackpad dan memeriksa perubahan bentuk SurfaceTransformation, animasi masuk EdgeButton, dan pergerakan ScrollIndicator secara real time.

Penjaga ScrollIndicator selama pengambilan scroll (LocalScrollCaptureInProgress)

Saat alat pengujian screenshot multi-frame atau Pengambilan Screenshot dengan Scroll (screenshot panjang) sistem mengambil TransformingLazyColumn yang dapat di-scroll, Compose menetapkan LocalScrollCaptureInProgress.current ke true saat mengambil dan menggabungkan beberapa petak area tampilan secara vertikal.

Karena ScreenScaffold tidak otomatis menyembunyikan scrollIndicator selama pengambilan scroll, overlay scrollbar mengambang akan muncul berulang di setiap ubin yang digabungkan dari screenshot panjang, kecuali jika Anda secara eksplisit melindunginya dengan !LocalScrollCaptureInProgress.current:

ScreenScaffold(
    scrollState = columnState,
    scrollIndicator = {
        if (!LocalScrollCaptureInProgress.current) {
            ScrollIndicator(state = columnState)
        }
    }
) { contentPadding ->
    // TransformingLazyColumn content...
    // ...
}