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


アプリは、あらゆるサイズの 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 の仕様。正しいパディングを決定します。
  • Text ヘッダーにはパディングがないため、リストの最初の項目に ListHeader を使用します。

詳細な仕様については、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 サンプルでは、GreetingScreen のテストは GreetingScreenTest に示すように実装されています。
@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 サンプルをご覧ください。