プロダクト ニュース

Jetpack Compose 2026 年 8 月リリースの新機能

所要時間: 5 分
Nick Butcher のプロフィールを表示
Nick Butcher プロダクト マネージャー

本日、Jetpack Compose の 2026 年 8 月リリースが安定版になりました。このリリースでは、コア Compose モジュール全体でバージョン 1.12 が導入され(BOM マッピングの完全版を参照)、メッシュ グラデーションや広色域(WCG)のサポートなどの豊富なビジュアル API、Grid の名前付き領域などの構造レイアウト機能、Android の Credential Manager とのシームレスな統合、テストとパフォーマンスの大幅な改善が導入されています。

プロジェクトを本日のリリースに更新するには、Compose BOM のバージョンを 2026.08.00 にアップグレードします。

implementation(platform("androidx.compose:compose-bom:2026.08.00"))

互換性を破る変更

  • AGP とコンパイル SDK: Compose 1.12 では、compileSdk が API 37 に更新され、最小 AGP 9.1.2 が必要になります。なお、Compose は常に最新の compileSdk をターゲットにします。この変更について詳しくは、こちらをご覧ください。
  • Modifier.onFirstVisible() が非推奨になりました: Modifier.onVisibilityChanged() に移行してください。これにより、可視性しきい値のトラッキングの精度が向上します。

グラフィック

メッシュ グラデーション

Compose 1.12 では、マルチポイントのオーガニック カラー グラデーションを作成するのに役立つ MeshGradientPainter が導入されています。

meshGradient.gif
val rows = 1
val columns = 1

val gradientPainter = remember {
    MeshGradientPainter(rows, columns) {
        // Parameters: row, column, position, color
        setVertex(0, 0, Offset(0f, 0f), Color.Red)     // Top-Left
        setVertex(0, 1, Offset(1f, 0f), Color.Blue)    // Top-Right
        setVertex(1, 0, Offset(0f, 1f), Color.Green)   // Bottom-Left
        setVertex(1, 1, Offset(1f, 1f), Color.Yellow)  // Bottom-Right
    }
}

Box(
    modifier = modifier
        .aspectRatio(16/9f)
        .fillMaxWidth()
        .paint(gradientPainter)
)

詳細と例については、ドキュメントをご覧ください。

広色域と HDR のサポート

最新のディスプレイは、色再現性が高く、ダイナミック レンジが広くなっています。Compose 1.12 では、Compose のグラフィック、ペイント、シェーダー全体で、広色域(P3)と HDR レンダリングのパイプラインの完全なサポートが有効になりました。非 sRGB 色空間(Display P3 など)で定義された色は、色をクランプすることなくプラットフォーム レンダリングまで保持されます。サポートされていない色空間(CieXyz、CieLab、Oklab など)を使用している場合、サポートされていない Android バージョンの色空間(Android 13 以前の Bt2020Hlg など)に依存している場合、またはアプリが Android 9(API 28)以下で実行されている場合、色は安全に sRGB にフォールバックされます。

その他の主な変更点:

  • LayerOutsets が GraphicsLayer と Modifier.graphicsLayer に追加されました。これを使用して、レイヤの視覚的な境界を測定されたサイズを超えて拡大できます。レイヤがオフスクリーン バッファに昇格されるときに、暗黙的な clipToBounds の動作を回避するために LayerOutsets を適用します。

スタイル

Google I/O では、Compose の Styles API の初期ビジョンを共有しました。これは、コンポーネントのスタイル設定を統一的かつ効率的に行うためのものです。それ以来、厳格な型安全と予測可能な正確性を保証し、カスタム デザイン システムの構築をサポートするために、基盤となるアーキテクチャの構築を続けています。

この基盤レイヤを正しく構築するため、API は試験運用中のままとなり、破壊的変更が発生する可能性があります。

ランタイムの最適化

キー付き SideEffect オーバーロード

SideEffect がキー引数をサポートするようになりました。これにより、特定のキーが変更されるたびに 1 回限りの副作用を発生させることができます。これにより、コルーチンや dispose ブロックが不要な場合に LaunchedEffect や DisposableEffect を使用するよりもパフォーマンスが向上します。SideEffect は LaunchedEffect よりも最大 90% 高速で、DisposableEffect よりも約 20% 高速です。SideEffect は DisposableEffect と LaunchedEffect の前に効果を実行するため、既存の効果をこの API に移行する場合は注意が必要です。特に、現在のフレームの完了後にディスパッチされることに依存する LaunchedEffects については注意してください。

@Composable
fun AnalyticsTracker(userId: String, screenName: String) {
    SideEffect(key1 = userId, key2 = screenName) {
        analytics.logScreenView(userId, screenName)
    }
}

アニメーション

インタラクティブな 2 段階のトランジション

  • 新しいコンポーザブル: DeferredAnimatedContent と DeferredAnimatedVisibility を使用すると、予測型「戻る」ジェスチャーのトラッキングなど、2 段階の楽しいトランジションを作成できます。
  • 手動アニメーション制御: 移行の遅延フェーズ中に、アニメーション プロパティ(スケールやオフセットなど)をリアルタイムで手動操作できるようになりました(スワイプ ジェスチャーのトラッキングなど)。
  • シームレスなハンドオフ: 遅延フェーズが終了すると、移行エンジンが引き継ぎ、速度の転送など、自動移行へのシームレスなハンドオフを実行します。
  • 共有要素のサポート: SharedContentConfig の新しい permitTransformDuringDeferredTransition フラグは、遅延遷移フェーズ中に共有要素が親コンテナとともに視覚的に変換されるかどうかを制御します。
val state = remember { DeferredTransitionState(initialScreen) }
val transition = rememberDeferredTransition(state)

if (predictiveBackInProgress) {
    state.defer(targetScreen)
} else {
    state.animateTo(targetScreen)
}

transition.DeferredAnimatedContent(
    targetState = targetScreen,
    mutableTransformSpec = {
       MutableContentTransform {
           // Manually manipulate properties during the deferred phase
           initialContentTransform { scale = swipeProgress }
       }
    }
) { screen ->
    ScreenContent(screen)
}

以下は、ジェスチャー駆動型のアニメーションがトリガー型のアニメーションに引き継がれるユースケースの 2 つのデモです。

colorCards.gif

テキスト、入力、プラットフォームの統合

編集可能なテキストの書式設定

新しい API は、BasicTextField の編集可能なテキストにリッチテキスト形式を提供します。TextFieldBuffer スコープ(textFieldState.edit { ... } や InputTransformation など)内の新しい addStyle() メソッドを介して SpanStyle と ParagraphStyle を使用して、インラインの文字と段落の書式設定をプログラムで適用および操作できるようになりました。また、TextFieldBuffer は TrackedRange オブジェクトを返す getSpanStyles() と getParagraphStyles() の API を提供します。これにより、適用されたスタイルを読み取り、更新、削除できます。書式設定の作成を補完するため、TextFieldState は範囲全体でアクティブなスタイルをクエリするための読み取り専用の textStyles プロパティを公開するようになりました。一方、TextFieldBuffer は編集前に書式設定の状態を検査するための originalTextStyles を提供します。テキストの書式設定とカスタム アノテーションは、構成の変更後も保持されます。

val state = rememberTextFieldState("Formatted text in Compose 1.12")

// Apply bold and color styles to a range of text
state.edit {
    addStyle(
        SpanStyle(fontWeight = FontWeight.Bold, color = Color.Blue),
        start = 0,
        end = 9
    )
}

// Query active styles from TextFieldState
val currentStyles = state.textStyles

テキストの選択

新しい SelectionState API は、SelectionContainer 内のテキスト選択に対するプログラムによる制御とオブザーバビリティを提供します。rememberSelectionState() を介して SelectionState オブジェクトをホイスティングし、SelectionContainer に渡すと、selectedTexts が AnnotatedStrings のリアクティブ リストとして公開され、selectAll()、clear()、select(TextRange)、extendSelectionByWord() などのメソッドが提供されます。

また、getSelectableTexts() を使用して、レイアウト順に選択可能なすべてのテキスト アイテムを取得し、グローバル範囲を使用して SelectionContainer のコンポーザブル全体でテキストを選択します。

@Composable
fun ProgrammaticSelectionExample() {
    val selectionState = rememberSelectionState()

    Column {
        Button(
            onClick = { selectionState.selectAll() },
            modifier = Modifier.disableSelectionClearOnTap()
        ) {
            Text("Select All")
        }

        SelectionContainer(state = selectionState) {
            Text("Text content to be selected programmatically.")
        }
    }
}

認証情報マネージャーの統合

Compose のテキスト フィールドが、自動入力フレームワークを介して Android の Credential Manager(API 34 以降)とネイティブに統合されるようになりました(API 34 より前の場合は androidx.credentials library で処理されます)。新しい credentialRequest セマンティクス プロパティを CredentialRequestData に関連付けることで、テキスト入力でパスキー、保存済みの認証情報、ログイン リクエストをユーザー入力フロー内で直接プロンプト表示できます。

@Composable
fun LoginField(textFieldState: TextFieldState) {
    val credentialData = remember {
        CredentialRequestData(
            // Specify Credential Manager request options
        )
    }

    BasicTextField(
        state = textFieldState,
        modifier = Modifier.semantics {
            credentialRequest = credentialData
        }
    )
}

その他の主な変更点:

  • ダウンロード可能なフォントのフォント バリエーション設定のサポート。
  • SelectionContainer で、テキスト選択をビューポート外にドラッグしたときに自動スクロールを有効にしました。
  • Compose コンポーネントに自動インタラクション サウンド(クリックとフォーカス ナビゲーション)のサポートを追加しました。また、オプトアウトを可能にする新しい SoundEffectOnInteraction コンポーザブルも追加しました。この変更の結果、セマンティクス クリック リスナーはメインスレッドから呼び出す必要があり、少数のテストケースに影響する可能性があります。
  • KeyboardType に Date、Time、DateTime、SignedDecimal が含まれるようになりました。
  • BasicSecureTextField はデフォルトで TextObfuscationMode.System を使用するようになり、RevealLastTyped は絶対的なオーバーライドとして機能します。

レイアウトの強化

グリッド レイアウトの名前付きエリア

@Experimental Grid コンポーネントの名前付き領域を使用して、複雑な 2D レイアウトを簡単に作成できるようになりました。数値の列と行のインデックスをアイテム間で管理するのではなく、GridConfigurationScope でセマンティック領域を定義し、領域名でコンポーザブルを配置できます。

@OptIn(ExperimentalGridApi::class)
@Composable
fun DashboardLayout() {
    Grid(
        config = {
            area("header", row = 0, column = 0, rowSpan = 1, columnSpan = 2)
            area("sidebar", row = 1, column = 0)
            area("content", row = 1, column = 1)
            gap(16.dp)
        }
    ) {
        HeaderSection(modifier = Modifier.gridItem(areaId = "header"))
        NavigationSidebar(modifier = Modifier.gridItem(areaId = "sidebar"))
        MainContentView(modifier = Modifier.gridItem(areaId = "content"))
    }
}

詳細については、ドキュメントをご覧ください。

パフォーマンス

すべてのリリースと同様に、Compose のパフォーマンスへの投資を継続し、このフレームワークが美しくパフォーマンスの高いアプリの構築に役立つようにしています。このリリースでは、起動パフォーマンスの改善に重点を置いており、ベンチマークで初期表示までの時間(アプリが最初のフレームを生成するのにかかる時間)が View と同程度になっています。

timetoinitialdisplay@2x _v2.png

テストとツール アップグレード

テストの同期

Compose 1.12 では、テスト実行時間を短縮し、状態サンプリング中の不安定さを解消するように設計された新しいテスト API が導入されています。

  • hasPendingWork: 時計を進めることなく UI に保留中の作業があるかどうかをパッシブにチェックします。これは手動のアニメーション ループに最適です。
  • runWithoutImplicitWait: 手動クロック フレーム(アニメーション テストなど)をステップ実行する際に、暗黙的な同期を一時的に無効にします。
@Test
fun testAnimationStateFast() {

composeTestRule.mainClock.autoAdvance = false
    
    while (composeTestRule.hasPendingWork()) {
        composeTestRule.mainClock.advanceTimeByFrame()
        composeTestRule.waitForIdle()
        
        composeTestRule.runOnUiThread {
            composeTestRule.runWithoutImplicitWait {
                // This is most effective when querying multiple nodes in a single frame. 
                // It prevents the redundant synchronization overhead that would 
                // otherwise occur on every individual query.
                val box1 = composeTestRule.onNodeWithTag("Box1").fetchSemanticsNode()
                val box2 = composeTestRule.onNodeWithTag("Box2").fetchSemanticsNode()
                
                assertThat(box1.boundsInRoot.right).isAtMost(box2.boundsInRoot.left)
            }
        }
    }
}

その他の主な変更点:

  • captureToImage API で、ポップアップまたはダイアログをアンカーとともに 1 つのビットマップでキャプチャできるようになりました。
  • Compose のセマンティック検索を特定の Android ビューに限定する onRootWithViewInteraction を追加しました。これにより、本番環境コードで一意のテストタグを必要とせずに、RecyclerViews などのハイブリッド UI のテストを簡素化できます。
  • @PreviewWrapper アノテーションをカスタム @MultiPreview クラスに適用できるようになりました。これにより、複数のコンポーネントで再利用可能なプレビュー設定(カスタムテーマなど)が可能になります。

Compose をぜひご活用ください。

Compose 1.12 では、メッシュ グラデーション、広色域のサポート、ダウンロード可能なバリアブル フォント、認証情報マネージャーの統合、高速なテストツールにより、アプリ開発がこれまで以上に簡単かつ表現豊かになります。Google では、常に皆様からの貴重なご意見をお待ちしています。これらの変更に関するフィードバックや、今後追加してほしい機能などがありましたら、問題トラッカーからお寄せください。Compose を使ったコーディングをお楽しみください。

作成者:
続きを読む