さまざまな画面サイズに合わせて開発する


アプリは、あらゆるサイズの Wear OS デバイスで適切に動作し、利用可能なスペースを活用しつつ、小さな画面でも見栄えよく表示する必要があります。このガイドでは、このようなユーザー エクスペリエンスを実現するための推奨事項について説明します。

アダプティブ レイアウトの設計原則について詳しくは、設計ガイダンスをご覧ください。

マテリアル 3 を使用してレスポンシブ レイアウトを作成する

レイアウトには割合ベースの余白が必要です。Compose はデフォルトで絶対値で動作するため、Horologist ライブラリrememberResponsiveColumnPadding を使用してパディングを計算し、ScreenScaffoldcontentPadding パラメータと TransformingLazyColumncontentPadding パラメータに渡します。

次のコード スニペットは、TransformingLazyColumn コンポーネントを使用して、さまざまな Wear OS 画面サイズで美しく見えるコンテンツを作成します。

val columnState = rememberTransformingLazyColumnState()
val contentPadding = rememberResponsiveColumnPadding(
    first = ColumnItemType.ListHeader,
    last = ColumnItemType.Button,
)
val transformationSpec = rememberTransformationSpec()
ScreenScaffold(
    scrollState = columnState,
    contentPadding = contentPadding
) { contentPadding ->
    TransformingLazyColumn(
        state = columnState,
        contentPadding = contentPadding
    ) {
        item {
            ListHeader(
                modifier = Modifier.fillMaxWidth().transformedHeight(this, transformationSpec),
                transformation = SurfaceTransformation(transformationSpec)
            ) {
                Text(text = "Header")
            }
        }
        // ... other items
        item {
            Button(
                modifier = Modifier.fillMaxWidth().transformedHeight(this, transformationSpec),
                transformation = SurfaceTransformation(transformationSpec),
                onClick = { /* ... */ },
                icon = {
                    Icon(
                        imageVector = Icons.Default.Build,
                        contentDescription = "build",
                    )
                },
            ) {
                Text(
                    text = "Build",
                    maxLines = 1,
                    overflow = TextOverflow.Ellipsis,
                )
            }
        }
    }
}

この例では、ScreenScaffoldAppScaffold も示しています。これらは、アプリと個々の画面(ナビゲーション ルート)を調整して、正しいスクロール動作と TimeText の配置を実現します。

上部と下部のパディングについては、次の点にも注意してください。

  • 最初の ItemType と最後の ItemType の仕様。正しいパディングを決定します。
  • リストの最初の項目に ListHeader を使用する。Text ヘッダーにはパディングを付けてはならないためです。

詳細な仕様については、Figma デザインキットをご覧ください。詳細と例については、以下をご覧ください。

  • Horologist ライブラリ - Wear OS 向けに最適化され、差別化されたアプリを構築するためのヘルパーを提供します。
  • ComposeStarter サンプル - このガイドで説明する原則を示したサンプル。
  • JetCaster サンプル - Horologist ライブラリを使用して、さまざまな画面サイズに対応するアプリを構築する、より複雑な例です。

アプリでスクロール レイアウトを使用する

画面を実装する際は、このページで説明したように、デフォルトでスクロール レイアウトを使用します。これにより、ディスプレイの設定や Wear OS デバイスの画面サイズに関係なく、ユーザーはアプリのコンポーネントにアクセスできます。

デバイスのサイズとフォント スケーリングの違いによる影響

デバイスのサイズとフォント スケーリングの違いによる影響。

ダイアログ

ダイアログは、そうしない理由がない限り、スクロール可能にする必要があります。 AlertDialog コンポーネントはレスポンシブで、コンテンツがビューポートの高さを超えるとデフォルトでスクロール可能になります。

カスタム画面ではスクロールしないレイアウトが必要になる場合があります

一部の画面では、スクロールしないレイアウトが適している場合があります。メディアアプリのメイン プレーヤー画面やフィットネス アプリのワークアウト画面などが例として挙げられます。

このような場合は、Figma デザインキットに記載されている標準的なガイダンスを確認し、正しい余白を使用して、画面のサイズに応じたデザインを実装します。

ブレークポイントで差別化されたエクスペリエンスを提供する

大型ディスプレイでは、追加のコンテンツや機能を導入できます。このような差別化されたエクスペリエンスを実装するには、画面サイズのブレークポイントを使用して、画面サイズが 225 dp を超えると別のレイアウトを表示します。

const val LARGE_DISPLAY_BREAKPOINT = 225

@Composable
fun isLargeDisplay() =
    LocalConfiguration.current.screenWidthDp >= LARGE_DISPLAY_BREAKPOINT

// ...
// ... use in your Composables:
    if (isLargeDisplay()) {
        // Show additional content.
    } else {
        // Show content only for smaller displays.
    }
    // ...

設計ガイダンスでは、こうした機会について詳しく説明しています。

プレビューを使用して画面サイズとフォントサイズの組み合わせをテストする

Compose プレビューを使用すると、さまざまな Wear OS 画面サイズ向けに開発できます。デバイスとフォント スケーリングのプレビュー定義の両方を使用して、次の情報を確認します。

  • サイズの極端な場合(最大フォントと最小画面の組み合わせなど)の画面の表示方法。
  • ブレークポイント間での差別化されたエクスペリエンスの動作。

アプリ内のすべての画面で WearPreviewDevicesWearPreviewFontScales を使用してプレビューを実装してください。

@WearPreviewDevices
@WearPreviewFontScales
@Composable
fun ComposeListPreview() {
    ComposeList()
}

スクリーンショット テスト

プレビュー テストに加えて、スクリーンショット テストでは、さまざまな既存のハードウェア サイズでテストできます。これは、問題が発生したデバイスをすぐに入手できない場合や、他の画面サイズでは問題が発生しない場合に特に便利です。

スクリーンショット テストは、コードベースの特定の場所での回帰を特定する場合にも役立ちます。

サンプルでは、スクリーンショット テストに Roborazzi を使用しています。

  1. Roborazzi を使用するようにプロジェクトアプリbuild.gradle ファイルを構成します。
  2. アプリ内の画面ごとにスクリーンショット テストを作成します。たとえば、ComposeStarter サンプルでは、GreetingScreenTest に示すように、GreetingScreen のテストが実装されています。
@RunWith(ParameterizedRobolectricTestRunner::class)
class GreetingScreenTest(override val device: WearDevice) : WearScreenshotTest() {
    override val tolerance = 0.02f

    @Test
    fun greetingScreenTest() = runTest {
        AppScaffold {
            GreetingScreen(greetingName = "screenshot", onShowList = {})
        }
    }

    companion object {
        @JvmStatic
        @ParameterizedRobolectricTestRunner.Parameters
        fun devices() = WearDevice.entries
    }
}

注意すべき重要な点:

  • WearDevice.entries には、最も一般的な Wear OS デバイスの定義が含まれているため、代表的な画面サイズの範囲でテストを実行できます。

ゴールデン イメージを生成する

画面の画像を生成するには、ターミナルで次のコマンドを実行します。

./gradlew recordRoborazziDebug

画像を確認する

既存のイメージに対する変更を確認するには、ターミナルで次のコマンドを実行します。

./gradlew verifyRoborazziDebug

スクリーンショット テストの完全な例については、ComposeStarter サンプルをご覧ください。