プロダクト ニュース

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 にフォールバックされます。

その他の重要な変更点:

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

スタイル

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

この基盤レイヤを正しく構築するため、API は試験運用中のままとなり、互換性を破る変更が予想されます。

ランタイムの最適化

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

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

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

アニメーション

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

  • 新しいコンポーザブルDeferredAnimatedContentDeferredAnimatedVisibility を使用すると、予測型「戻る」ジェスチャーのトラッキングなど、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() メソッドを介して SpanStyleParagraphStyle を使用して、インラインの文字と段落の書式設定をプログラムで適用および操作できるようになりました。また、TextFieldBufferTrackedRange オブジェクトを返す 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 に渡すと、selectedTextsAnnotatedStrings のリアクティブ リストとして公開され、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.")
        }
    }
}

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

テキストフィールドは、Autofill フレームワークを介して 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 も追加しました。この変更の結果、セマンティクス クリック リスナーはメインスレッドから呼び出す必要があり、少数のテストケースに影響する可能性があります。
  • KeyboardTypeDateTimeDateTimeSignedDecimal が含まれるようになりました。
  • 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 のパフォーマンスへの投資を継続し、このフレームワークが美しくパフォーマンスの高いアプリの構築に役立つようにします。このリリースでは、起動パフォーマンスの改善に重点を置いており、ベンチマークで Views と同程度の初期表示までの時間(アプリが最初のフレームを生成するのにかかる時間)を確認できるようになりました。

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 では、メッシュ グラデーション、広色域のサポート、ダウンロード可能なバリアブル フォント、認証情報マネージャーの統合、高速なテストツールなどにより、アプリ開発がこれまで以上に簡単かつ表現豊かになります。いつものように、皆様からのご意見を重視しております。これらの変更や、今後追加してほしい機能について、Issue Tracker からフィードバックをお寄せください。Compose をお楽しみください。

作成者:
続きを読む