mcpField
J
jetpack-compose-m3

jetpack-compose-m3

github.com/android開発10.0k296 回インストール2 日前に更新
リポジトリ

jetpack-compose-m3 について

Wear Compose Material3 を使った Wear OS UI の構築と移行を支援するスキルです。バージョンやサンプルの確認、コンポーネントの使い方、Wear 向けレイアウトとナビゲーションの規則を案内します。

主な機能

  1. 01Wear Compose Material3 の移行ガイド
  2. 02バージョンと互換性の確認
  3. 03コンポーネントサンプルの確認
  4. 04Scaffold とリストレイアウトの指針
  5. 05Material テーマとデフォルト値
  6. 06Wear のナビゲーション規則

活用シーン

  1. 01旧 Wear Compose 画面の移行
  2. 02Wear Material3 コンポーネントの追加
  3. 03スクロール可能な Wear OS 画面の構築

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/android/skills --skill jetpack-compose-m3

インストール後、Claude Code で/jetpack-compose-m3を入力して読み込まれたか確認します。

同梱ファイルreferences/android/training/wearables/compose/migrate-to-material3.md

詳細

前提条件と互換性

  1. Wear OS Compose Material3 のバージョン: androidx.wear.compose:compose-material3 の最新の安定版 {VERSION} を特定するための内部ツールが利用できる場合は、そのツールを使用してください。
    • 利用できない場合は、公式の Maven メタデータ XMLを取得して {VERSION} を特定してください(-alpha、-beta、-rc を除いたうえで、最も大きい番号を選びます)。
  2. 厳格な遵守: 安定版として記載されているバージョンがある場合、ユーザーから別途指示がない限り、必ずそのバージョンを使用してください。エディターで最初に「Unresolved reference」エラーが発生した場合や、ウェブ検索結果が古い場合でも、バージョンを下げてはいけません。
  3. Kotlin のバージョン: Wear Compose Material3 では、Kotlin 2.0.0 以上を使用してください。
  4. Compose コンパイラー:
    • Kotlin のバージョンが 2.0.0 以上の場合、プロジェクトでは org.jetbrains.kotlin.plugin.compose Gradle プラグインを使用する必要があります。
    • Kotlin のバージョンが 2.0.0 未満の場合、プロジェクトでは composeOptions の kotlinCompilerExtensionVersion を使用し、Compose と Kotlin の互換性マップに合わせる必要があります。
  5. 最小 SDK: minSdk が 25(Wear OS 2.0)以上であることを確認してください。
  6. サンプル抽出の必須要件: Wear Compose ライブラリには、すべてのコンポーネントの個別サンプルを含む追加の JAR ファイルが付属しています。Capability 2 のサンプルをローカルキャッシュに抽出するまでは、コードの変更を提案してはいけません。ライブラリのソースファイルは不完全であり、これらのサンプルの代わりにはなりません。抽出を省略することは、環境設定の不備にあたります。

注意事項

  1. 同期と検証の必須要件: libs.versions.toml または build.gradle.kts のバージョンを更新した後は、コードをリファクタリングする前に、必ず Gradle の同期を実行してください。これにより、環境でライブラリが正しく解決されていることを確認できます。
  2. 推測の禁止(エラープロトコル): 同期の成功後に「Unresolved Reference」または API の不一致が発生した場合、ライブラリのバージョンを下げて「修正」しようとしてはいけません。

機能とツール

機能 1:移行

古いバージョンの Wear OS Compose または Horologist から移行する場合は、このガイダンスを使用してください。

  1. 開発者から別途指示がない限り、{VERSION} の Wear Compose Material3 最新安定版を使用してください。
  2. 移行ガイドを読んでください。
  3. 移行ガイドに記載されている公式のコンポーネント対応表を使用してください。
  4. コンポーネント(例:Chip -> Button)をリファクタリングする前に、パラメーター名、スロットの型、「Expressive」デザイントークンを確認してください。
  5. Horologist の Composable、Compose Layout、Compose Material ライブラリは使用しないでください。
  6. 必ず機能 3 のコンポーネントに関するガイダンスを確認してください。
  7. 移行後にスクリーンショットテストが失敗することを想定してください。非常によく似たコンポーネントへの移行であっても、パディングや配置のデフォルト値は変わっています。移行前のスクリーンショットに人為的に一致させようとせず、Material3 のデフォルト値を優先してください。
機能 2:コンポーネントのサンプル

Wear Compose には、<artifact>-<version>-samples-sources.jar ファイルに、すべてのコンポーネントの個別サンプルが含まれています。compose-material3、compose-foundation、compose-navigation3 のいずれかを使用すると、Gradle はこれらの JAR ファイルをメインライブラリの JAR と一緒に自動的にダウンロードします。

Wear Compose Material3 のコンポーネントを追加または調整する場合は、常に正式なコンポーネントサンプルを使用してください。

厳格な遵守:抽出は任意ではありません。サンプルを抽出して読み込むまで、コードを実装することは禁止されています。別の検索ツールを使ったり、ライブラリのドキュメントだけで十分だと判断してこの手順を省略することは、プロトコル違反です。先に進む前にサンプルファイルを読み、ローカルキャッシュを検証する必要があります。

手順 1:準備
  1. build.gradle.kts または libs.versions.toml を確認し、Wear Compose のバージョンが {VERSION} と一致していることを確認します。
  2. Gradle の同期を実行して、必要な依存関係がダウンロードされていることを確認します。
手順 2:ローカルキャッシュを確認
  1. キャッシュディレクトリのパスを定義します:<SKILL_ROOT>/samples/{VERSION}/。別の場所を独自に選ばないでください。
  2. このディレクトリが存在し、.kt ファイルを含むサブディレクトリがあるか確認します。
    • はい(キャッシュヒット): 手順 4 に進みます。
    • いいえ(キャッシュミス): 手順 3 に進みます。
手順 3:Gradle キャッシュを確認
  1. サンプルソースは Gradle キャッシュに保存されています。時間のかかる総当たり検索を避けるため、次の手順を実行します。

    • Gradle ユーザーホームを特定します(通常は ~/.gradle です。または $GRADLE_USER_HOME を確認します)。
    • キャッシュのルートは <GRADLE_USER_HOME>/caches です。これを <CACHE_ROOT> と呼びます。
  2. {ARTIFACT} をリスト ["material3", "foundation"] の項目として定義します。androidx.wear.compose.navigation3 ライブラリを使用している場合は、"navigation3" もリストに追加します。

  3. リスト内の各 {ARTIFACT} について、次の手順を実行します。

    • ライブラリの相対パス部分を次のように組み立てます:androidx.wear.compose/compose-{ARTIFACT}/{VERSION}。

    • 対象を絞った find コマンドを実行します。効率を高めるための例を次に示します。

      find <CACHE_ROOT>/modules-2/files-2.1/androidx.wear.compose/compose-{ARTIFACT}/{VERSION}/ \
        -name "*samples-sources.jar"
      
  4. この JAR を正式なサンプルソースとして使用します。

  5. 各 JAR の内容を unzip -j を使って <SKILL_ROOT>/samples/{VERSION}/{ARTIFACT}/ に展開し、ディレクトリ構造をフラット化します。

  6. 手順 4 に直接進みます。

手順 4:サンプルを読み、実装する
  1. 関連する .kt サンプルファイルを読みます。
  2. バージョンが一致するこれらの公式サンプルを、次の項目の信頼できる情報源として使用します。
    • 必須パラメーターとスロット名。
    • デフォルトのスタイル設定とタイポグラフィのトークン。
    • インタラクティブな動作(例:onClick、onLongClick)。
    • コンポーネントのネスト(例:AppScaffold -> ScreenScaffold)。
機能 3:コンポーネントのガイダンス

必須:コンポーネントを使用する際は、この機能をチェックリストとして使用してください。コンポーネントの構文だけでなく、実際に各コンポーネントを使用する方法について、より包括的なガイダンスを提供します。

  1. AppScaffold と ScreenScaffold

    • [ ] 外側のコンテナとして AppScaffold を使用し、その子要素として ScreenScaffold を配置します。
    • [ ] AppScaffold は1つだけ使用し、ScreenScaffold は任意の数だけ使用します。
  2. ScalingLazyColumn - 代わりに TransformingLazyColumn を使用します。

  3. TransformingLazyColumn - 次のインポートが必要です:

    import androidx.wear.compose.foundation.lazy.TransformingLazyColumn
    import androidx.wear.compose.foundation.lazy.TransformingLazyColumnDefaults
    import androidx.wear.compose.foundation.lazy.rememberTransformingLazyColumnState
    // ...
    import androidx.wear.compose.material3.lazy.rememberTransformationSpec
    import androidx.wear.compose.material3.lazy.transformedHeight
    

    標準的な例:

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

    • [ ] ScalingLazyColumn の代わりに TransformingLazyColumn を使用します。
    • [ ] ScreenScaffold から contentPadding パラメーターを TransformingLazyColumn に渡す必要があります。
    • [ ] 必要な上下のパディングを設定するには、minimumVerticalContentPadding 修飾子を使用します。
      • ButtonDefaults、CardDefaults、`ListHeaderDefaults など、デフォルト値のいずれかを指定します。
      • 注:これは TransformingLazyColumnItemScope 内で使用できるスコープ付き修飾子です。
    • [ ] リストが形状を変化させながら拡大縮小することを確認します。
    • [ ] transformedHeight 修飾子を使用します。
    • [ ] transform = SurfaceTransform(...) を使用します。
    • [ ] リストでスナップを設定する場合は、flingBehavior と rotaryScrollableBehavior を一緒に使用します:
    val columnState = rememberTransformingLazyColumnState()
    ScreenScaffold(scrollState = columnState) { contentPadding ->
        TransformingLazyColumn(
            state = columnState,
            flingBehavior = TransformingLazyColumnDefaults.snapFlingBehavior(columnState),
            rotaryScrollableBehavior = RotaryScrollableDefaults.snapBehavior(columnState)
        ) {
            // ...
            // ...
        }
    }
    

  4. ScreenScaffold

    • [ ] !LocalScrollCaptureInProgress.current を条件にして scrollIndicator を表示します。
  5. EdgeButton

    • [ ] TransformingLazyColumn の最後の項目として使用しないでください。代わりに、ScreenScaffold のスロットを使用します。
    • [ ] TransformingLazyColumn 内で使用する場合は、必要なオーバースクロール動作を追加します:
    val columnState = rememberTransformingLazyColumnState()
    ScreenScaffold(
        scrollState = columnState,
        edgeButton = {
            EdgeButton(
                onClick = { /* TODO */ },
                modifier = Modifier.scrollable(
                    columnState,
                    orientation = Orientation.Vertical,
                    reverseDirection = true,
                    // Apply overscroll to the EdgeButton for proper scrolling behavior.
                    overscrollEffect = rememberOverscrollEffect(),
                )
            ) {
                Text("More")
            }
        }
    ) { contentPadding ->
        TransformingLazyColumn(
            contentPadding = contentPadding,
            state = columnState,
        ) {
            // ...
            // ...
        }
    }
    

  6. Column

    • [ ] システムフォントを最大にしても画面がスクロールしない場合に限り、ScreenScaffold の直接の子要素として使用します。
    • [ ] それ以外の場合は、代わりに TransformingLazyColumn を使用します。
  7. スタイル

    • [ ] テキストサイズをハードコードしないでください。MaterialTheme の typography を使用します。
    • [ ] 色をハードコードしないでください。MaterialTheme の colorScheme を使用します。
  8. コンポーネントのデフォルト値を使用します:

    • [ ] Button などのコンポーネントには、対応する ButtonDefaults オブジェクトがあります。
    • パディングやスタイルの値を扱う際は、ハードコードされた値よりも、各コンポーネントの *Defaults オブジェクトを確認して使用してください。
  9. Wear 固有のプレビューを使用します:

    • [ ] WearPreviewDevices
    • [ ] WearPreviewFontScales
  10. アンビエントモード

    • [ ] AmbientLifecycleObserver の代わりに LocalAmbientModeManager を使用します。
  11. ナビゲーション

    • [ ] 新たにナビゲーションを追加する場合は、Navigation3 を使用します。
    • [ ] Wear OS で Navigation3 を使用する場合は、Wear Compose の compose-navigation3 ライブラリにある SwipeDismissableSceneStrategy() を使用します。

コメント