Android Studio の Compose プレビューを使用すると、IDE で直接、さまざまなスマートウォッチのディスプレイ サイズ、丸いベゼル、フォント スケールにわたって Wear OS コンポーザブルを検査して検証できます。アプリを実際のスマートウォッチやエミュレータにデプロイする必要はありません。
Wear OS デバイスは、角がコンテンツを切り取り、TimeText や ScrollIndicator などのシステム オーバーレイが画面の端に沿ってカーブする円形のディスプレイを備えているため、レイアウトの問題を早期に検出するには、Wear OS 専用のプレビューを構成することが不可欠です。
プレビューの依存関係を設定する
Wear OS Compose のプレビュー アノテーションとデバイス定義を使用するには、モジュールの build.gradle.kts ファイルに次の依存関係を追加します。
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")
}
プレビューする対象(画面またはコンポーネント)を選択する
プレビューの構成方法は、全画面をプレビューするか、分離された UI コンポーネントをプレビューするかによって異なります。
全画面表示をプレビューする(AppScaffold + ScreenScaffold)
画面全体をプレビューする場合は、Wear デバイスのプレビュー アノテーションを使用して、画面コンポーザブルを常に AppScaffold と ScreenScaffold の両方でラップします。これにより、円形のスマートウォッチ ディスプレイがレンダリングされ、次のことが保証されます。
TimeTextは、文字盤の上部の曲がったエッジにレンダリングされます。- 右側のベゼルに
ScrollIndicatorが表示されます。 EdgeButtonが適切に配置され、下部の曲線でクリップされている。- コンテンツのパディングと円形画面のクリッピングが、実際のスマートウォッチのハードウェアを正確に反映します。
@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" ) } } }
Small Round(192x192dp)
大きな円形(227×227dp)
分離されたコンポーネントをプレビューする
カスタムの Card、Button、ステータス チップなどの個々のコンポーネントをプレビューする場合は、device パラメータを省略し、暗い背景の標準の @Preview を使用します。これにより、円形の時計ディスプレイ全体をレンダリングしなくても、Wear Material 3 の色とコントラストが正確に表示されます。
@Preview( showBackground = true, backgroundColor = 0xFF000000 ) @Composable fun HeartRateCardPreview() { MaterialTheme { HeartRateCard(bpm = 142, zone = "Aerobic") } }
分離されたコンポーネントのプレビュー(デバイス フレームなし)。
組み込みのマルチプレビュー アノテーション
androidx.wear.compose.ui.tooling.preview パッケージには、暗い背景(backgroundColor = 0xFF000000、showBackground = true)と円形のスマートウォッチの寸法を自動的に構成する組み込みのアノテーションが用意されています。
| Annotation | レンダリングされる内容 | 使用する場面 |
|---|---|---|
@WearPreviewSmallRound |
WearDevices.SMALL_ROUND のプレビュー 1 つ(192×192 dp)。 |
最も制約の厳しい円形表示サイズでの迅速なイテレーション。 |
@WearPreviewLargeRound |
WearDevices.LARGE_ROUND(227×227 dp)のプレビュー 1 つ。 |
大きなスマートウォッチのレイアウト密度と余分なスペースを検査。 |
@WearPreviewDevices |
2 つのプレビュー: SMALL_ROUND と LARGE_ROUND。 |
すべての画面コンポーザブルの標準マルチデバイス チェック。 |
@WearPreviewFontScales |
すべての Wear フォントスケール(小(0.94f)、標準(1.0f)、中(1.06f)、大(1.12f)、大(1.18f)、最大(1.24f))で SMALL_ROUND の 6 つのプレビュー。 |
テキストの折り返し、省略記号、ボタンの高さの拡張を確認しています。 |
@WearPreviewDevices と @WearPreviewFontScales を同じプレビュー関数にスタックして、包括的なテスト マトリックスを生成できます。
@WearPreviewDevices @WearPreviewFontScales @Composable fun MessageDetailScreenPreview() { MaterialTheme { AppScaffold { MessageDetailScreen( sender = "Alex", body = "Running 5 mins late!" ) } } }
カスタム プレビューのアノテーションとハードウェア仕様
特定のハードウェアの寸法、長いローカライズされた文字列、最悪の組み合わせなどをテストするなど、より細かい制御が必要な場合は、@Preview を直接構成するか、独自のカスタム マルチプレビュー アノテーションを定義できます。
利用可能な WearDevices 定数とカスタム ハードウェア仕様
androidx.wear.tooling.preview.devices.WearDevices オブジェクトは、標準のデバイス ID を提供します。
WearDevices.SMALL_ROUND("id:wearos_small_round"、192x192dp)WearDevices.LARGE_ROUND("id:wearos_large_round"、227×227 dp)
特大の丸型ディスプレイ(44 ~ 45 mm のスマートウォッチや 240×240 dp の Ultra モデルなど)でプレビューするには、カスタムの spec: 文字列を 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") } } }
カスタム マルチプレビュー アノテーションを作成する
極端なシナリオを検査するには、最小の丸型スクリーンと最大のフォントスケール、詳細なロケール(ドイツ語など)を標準の大型丸型スクリーンと組み合わせるカスタムのマルチプレビュー アノテーションを作成します。
@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
1. 標準の大きな円形
2. Extreme Small Round(最大フォント + ドイツ語)
スクロールする列をプレビューする(TransformingLazyColumn)
デフォルトでは、TransformingLazyColumn は最初のアイテム(index = 0)が画面の上部に固定された状態で初期化されます。ただし、Wear OS では、アイテムが画面の上端と下端の曲線に近づくにつれて、高さと角の丸み(SurfaceTransformation)が変化し、EdgeButton は下端までスクロールしたときにのみ表示されます。
リストを途中でスクロールした場合や、リストの末尾までスクロールした場合のリストの表示をプレビューするには:
ステップ 1: 画面コンポーザブルで TransformingLazyColumnState をホイストする
画面コンポーザブルが rememberTransformingLazyColumnState() をデフォルト値とする TransformingLazyColumnState パラメータを受け入れるようにします。
@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) } } } } }
ステップ 2: @Preview で initialAnchorItemIndex を渡す
rememberTransformingLazyColumnState は、省略可能な初期スクロール パラメータを 2 つ受け取ります。
initialAnchorItemIndex: Int: 負でないインデックス(3など)に設定すると、リストはその項目で初期化され、ウォッチのビューポートの中央に配置されます。initialAnchorItemScrollOffset: Int: 中央に配置されたアンカー アイテムを基準に適用される、省略可能なピクセル オフセット。
まったく同じ画面の [上]、[中(スクロール)]、[下(EdgeButton が表示)] の状態を示す並列プレビューを作成できます。
@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 ) ) } } }
上(デフォルト -1)
中(initialAnchorItemIndex = 3)
下部(EdgeButton 展開)
ヒント: Android Studio の任意の
@Previewで [Start Interactive Mode] をクリックして、マウスまたはトラックパッドでTransformingLazyColumnをスクロールし、SurfaceTransformationのモーフィング、EdgeButtonのエントランス アニメーション、ScrollIndicatorの動きをリアルタイムで検査することもできます。
スクロール キャプチャ(LocalScrollCaptureInProgress)中の ScrollIndicator をガード
システム スクロール キャプチャ(長いスクリーンショット)またはマルチフレーム スクリーンショット テストツールがスクロールする TransformingLazyColumn をキャプチャすると、Compose は、複数のビューポート タイルを縦方向にキャプチャしてステッチしている間、LocalScrollCaptureInProgress.current を true に設定します。
ScreenScaffold はスクロール キャプチャ中に scrollIndicator を自動的に非表示にしないため、!LocalScrollCaptureInProgress.current で明示的に保護しない限り、長いスクリーンショットのすべてのステッチ タイルにフローティング スクロールバー オーバーレイが繰り返し表示されます。
ScreenScaffold( scrollState = columnState, scrollIndicator = { if (!LocalScrollCaptureInProgress.current) { ScrollIndicator(state = columnState) } } ) { contentPadding -> // TransformingLazyColumn content... // ... }