Skip to content

Compose Multiplatform 1.7.3の新機能

このフィーチャーリリースの主なハイライトは以下の通りです。

このリリースの変更点の全リストはGitHubで確認できます。

依存関係

破壊的変更

最小AGPバージョンが8.1.0に引き上げられました

Compose Multiplatform 1.7.0で使用されているJetpack Compose 1.7.0とLifecycle 2.8.0のいずれも、AGP 7をサポートしていません。 そのため、Compose Multiplatform 1.7.3にアップデートする際には、AGPの依存関係もアップグレードする必要があるかもしれません。

Android Studioで新たに実装されたAndroidコンポーザブルのプレビューには、最新のAGPバージョンのいずれかが必要です。

JavaリソースAPIはマルチプラットフォームリソースライブラリに優先して非推奨になりました

このリリースでは、compose.uiパッケージで利用可能なJavaリソースAPIを明示的に非推奨とします。 具体的には、painterResource()loadImageBitmap()loadSvgPainter()loadXmlImageVector() 関数、 ならびに ClassLoaderResourceLoader クラスおよびそれに依存する関数です。

マルチプラットフォームリソースライブラリへの移行を検討してください。 JavaリソースをCompose Multiplatformで使用することはできますが、生成されたアクセサー、マルチモジュールサポート、ローカライゼーションなど、フレームワークが提供する拡張機能の恩恵を受けることはできません。

それでもJavaリソースにアクセスする必要がある場合は、プルリクエストで提案されている実装をコピーすることで、Compose Multiplatform 1.7.3にアップグレードし、可能な限りマルチプラットフォームリソースに切り替えた後でもコードが動作することを確認できます。

iOSネイティブ要素でのタッチ処理の新しいデフォルト動作

1.7.3以前では、Compose Multiplatformは相互運用UIビューに着地したタッチイベントに応答できず、相互運用ビューがこれらのタッチシーケンスを完全に処理していました。

Compose Multiplatform 1.7.3では、相互運用タッチシーケンスを処理するためのより洗練されたロジックが実装されています。 デフォルトでは、最初のタッチ後に遅延が設けられるようになり、これにより親コンポーザブルがタッチシーケンスがネイティブビューとのインタラクションを意図したものかどうかを理解し、それに応じて反応するのに役立ちます。

詳細については、このページのiOSセクションでの説明を参照するか、この機能のドキュメントをお読みください。

iOSでの最小フレーム期間の無効化は必須です

開発者は、高リフレッシュレートディスプレイに関する出力される警告に気付かないことが多く、ユーザーは120Hz対応デバイスでスムーズなアニメーションを利用できませんでした。 現在、このチェックを厳密に強制しています。Info.plistファイル内のCADisableMinimumFrameDurationOnPhoneプロパティが存在しないかfalseに設定されている場合、Compose Multiplatformでビルドされたアプリはクラッシュするようになります。

この動作を無効にするには、ComposeUIViewControllerConfiguration.enforceStrictPlistSanityCheckプロパティをfalseに設定します。

デスクトップ版のModifier.onExternalDragは非推奨になりました

実験的なModifier.onExternalDragおよび関連APIは、新しいModifier.dragAndDropTargetに優先して非推奨になりました。 DragDataインターフェースはcompose.ui.draganddropパッケージに移動されました。

Compose Multiplatform 1.7.0で非推奨のAPIを使用している場合、非推奨エラーに遭遇します。 1.8.0では、onExternalDragモディファイアは完全に削除される予定です。

クロスプラットフォーム

共有要素トランジション

Compose Multiplatformは、一貫した要素を共有するコンポーザブル間のシームレスなトランジションのためのAPIを提供するようになりました。 これらのトランジションは、ユーザーがUIの変更の軌跡を追うのに役立つため、ナビゲーションでよく利用されます。

APIの詳細については、Jetpack Composeドキュメントを参照してください。

型安全なナビゲーション

Compose Multiplatformは、Jetpack Composeの型安全なアプローチを採用し、ナビゲーションルートに沿ってオブジェクトを渡すようになりました。 Navigation 2.8.0の新しいAPIにより、Composeはナビゲーショングラフのコンパイル時の安全性を確保できるようになります。 これらのAPIは、XMLベースのナビゲーションにおけるSafe Argsプラグインと同じ結果を実現します。

詳細は、GoogleのNavigation Composeにおける型安全性に関するドキュメントを参照してください。

マルチプラットフォームリソース

Androidアセットにパッケージ化されたリソース

すべてのマルチプラットフォームリソースがAndroidアセットにパッケージ化されるようになりました。これにより、Android StudioでAndroidソースセット内のCompose Multiplatformコンポーザブルのプレビューを生成できます。

Android StudioのプレビューはAndroidソースセット内のコンポーザブルでのみ利用可能です。 また、最新バージョンのAGP (8.5.2、8.6.0-rc01、または8.7.0-alpha04) のいずれかが必要です。

これにより、Android上のWebViewやメディアプレーヤーコンポーネントからマルチプラットフォームリソースに直接アクセスできるようになりました。 例えば、Res.getUri(“files/index.html”)のようなシンプルなパスでリソースにアクセスできます。

以下は、リソースHTMLページとリソース画像へのリンクを表示するAndroidコンポーザブルの例です。

kotlin
// androidMain/kotlin/com/example/webview/App.kt
@OptIn(ExperimentalResourceApi::class)
@Composable
@Preview
fun App() {
    MaterialTheme {
        val uri = Res.getUri("files/webview/index.html")

        // Adding a WebView inside AndroidView with layout as full screen.
        AndroidView(factory = {
            WebView(it).apply {
                layoutParams = ViewGroup.LayoutParams(
                    ViewGroup.LayoutParams.MATCH_PARENT,
                    ViewGroup.LayoutParams.MATCH_PARENT
                )
            }
        }, update = {
            it.loadUrl(uri)
        })
    }
}

この例は、以下のシンプルなHTMLファイルで動作します。

html
<html>
<header>
    <title>
        Cat Resource
    </title>
</header>
<body>
    <img src="cat.jpg">
</body>
</html>

この例の2つのリソースファイルは、commonMainソースセットに配置されています。

composeResourcesディレクトリのファイル構造

カスタムリソースディレクトリ

新しいcustomDirectory設定を構成DSLで使用すると、特定のソースセットにカスタムディレクトリを関連付けることができます。これにより、例えば、ダウンロードしたファイルをリソースとして使用することが可能になります。

マルチプラットフォームフォントキャッシュ

Compose Multiplatformは、Androidのフォントキャッシュ機能を他のプラットフォームにも提供し、Fontリソースの過剰なバイト読み取りを排除します。

マルチプラットフォームテストリソースのサポート

リソースライブラリは、プロジェクトでのテストリソースの使用をサポートするようになり、以下のことが可能になります。

  • テストソースセットにリソースを追加する。
  • 対応するソースセットでのみ利用可能な生成されたアクセサーを使用する。
  • テスト実行時のみ、テストリソースをアプリにパッケージ化する。

アクセスを容易にするために文字列IDにマッピングされたリソース

各タイプのリソースは、ファイル名とマッピングされています。例えば、Res.allDrawableResourcesプロパティを使用して、すべてのdrawableリソースのマップを取得し、その文字列IDを渡すことで必要なリソースにアクセスできます。

kotlin
Image(painterResource(Res.allDrawableResources["compose_multiplatform"]!!), null)

バイト配列をImageBitmapまたはImageVectorに変換する関数

ByteArrayを画像リソースに変換するための新しい関数が追加されました。

  • decodeToImageBitmap()は、JPEG、PNG、BMP、またはWEBPファイルをImageBitmapオブジェクトに変換します。
  • decodeToImageVector()は、XMLベクターファイルをImageVectorオブジェクトに変換します。
  • decodeToSvgPainter()は、SVGファイルをPainterオブジェクトに変換します。この関数はAndroidでは利用できません。

詳細については、ドキュメントを参照してください。

新しい共通モジュール

material3.adaptive:adaptive*

Material3アダプティブモジュールが、Compose Multiplatformで共通コードとして利用可能になりました。 これらを使用するには、モジュールのbuild.gradle.ktsファイルで、対応する依存関係をcommonMainソースセットに明示的に追加します。

kotlin
commonMain.dependencies {
    implementation("org.jetbrains.compose.material3.adaptive:adaptive:1.0.0-alpha03")
    implementation("org.jetbrains.compose.material3.adaptive:adaptive-layout:1.0.0-alpha03")
    implementation("org.jetbrains.compose.material3.adaptive:adaptive-navigation:1.0.0-alpha03")
}

material3.material3-adaptive-navigation-suite

Composeでアダプティブナビゲーションを構築するために必要なMaterial3アダプティブナビゲーションスイートが、Compose Multiplatformで共通コードとして利用可能になりました。 これを使用するには、モジュールのbuild.gradle.ktsファイルで、依存関係をcommonMainソースセットに明示的に追加します。

kotlin
commonMain.dependencies {
    implementation(compose.material3AdaptiveNavigationSuite)
}

material3:material3-window-size-class

WindowSizeClassクラスを使用するには、モジュールのbuild.gradle.ktsファイルで、material3-window-size-class依存関係をcommonMainソースセットに明示的に追加します。

kotlin
commonMain.dependencies {
    implementation("org.jetbrains.compose.material3:material3-window-size-class:1.7.3")
}

calculateWindowSizeClass()関数は、まだ共通コードでは利用できません。 ただし、プラットフォーム固有のコードでインポートして呼び出すことはできます。例:

kotlin
// desktopMain/kotlin/main.kt
import androidx.compose.material3.windowsizeclass.calculateWindowSizeClass

// ...

val size = calculateWindowSizeClass()

material-navigation

material-navigationライブラリは、Compose Multiplatform Navigationに加えて、共通コードで利用可能です。 これを使用するには、モジュールのbuild.gradle.ktsファイルで、以下の明示的な依存関係をcommonMainソースセットに追加します。

kotlin
commonMain.dependencies {
    implementation("org.jetbrains.androidx.navigation:navigation-compose:2.8.0-alpha10")
    implementation("org.jetbrains.compose.material:material-navigation:1.7.0-beta02")
}

SkiaがMilestone 126にアップデートされました

Compose MultiplatformがSkiko経由で使用しているSkiaのバージョンがMilestone 126にアップデートされました。

以前のSkiaのバージョンはMilestone 116でした。これらのバージョン間の変更点は、リリースノートで確認できます。

GraphicsLayer – 新しい描画API

Jetpack Compose 1.7.0で追加された新しい描画レイヤーが、Compose Multiplatformでも利用可能になりました。

Modifier.graphicsLayerとは異なり、新しいGraphicsLayerクラスを使用すると、Composableコンテンツをどこにでもレンダリングできます。 これは、アニメーションコンテンツが異なるシーンでレンダリングされることが期待される場合に役立ちます。

詳細な説明と例については、リファレンスドキュメントを参照してください。

LocalLifecycleOwnerがCompose UIから移動されました

LocalLifecycleOwnerクラスが、Compose UIパッケージからLifecycleパッケージに移動されました。

この変更により、Compose UIに依存せずにクラスにアクセスし、ComposeベースのヘルパーAPIを呼び出すことができます。 ただし、Compose UIバインディングがない場合、LocalLifecycleOwnerインスタンスにはプラットフォーム統合がなく、プラットフォーム固有のイベントをリッスンできないことに注意してください。

iOS

Compose MultiplatformとネイティブiOS間のタッチ相互運用性の改善

このリリースでは、iOSの相互運用ビューのタッチハンドリングが改善されました。 Compose Multiplatformは、タッチが相互運用ビューを意図しているのか、それともComposeで処理されるべきなのかを検出するようになりました。 これにより、Compose Multiplatformアプリ内のUIKitまたはSwiftUI領域で発生するタッチイベントを処理することが可能になります。

デフォルトでは、Compose Multiplatformはタッチイベントを相互運用ビューに送信するのを150ミリ秒遅延させます。

  • この時間枠内にしきい値を超える移動があった場合、 親のコンポーザブルがタッチシーケンスをインターセプトし、相互運用ビューには転送されません。
  • 顕著な移動がない場合、Composeはタッチシーケンスの残りを処理せず、 代わりに相互運用ビューが単独で処理します。

この動作は、ネイティブのUIScrollViewの動作と一致しています。 これにより、相互運用ビューで始まったタッチシーケンスが、Compose Multiplatformがそれを認識する機会もなくインターセプトされてしまう状況を防ぐことができます。これはユーザーにとって不満な体験につながる可能性があります。 例えば、レイジーリストのようなスクロール可能なコンテキストで、画面の大部分を占める大きな相互運用ビデオプレーヤーがある場合を想像してみてください。 ビデオがすべてのタッチをインターセプトし、Compose Multiplatformがそれらを認識していない場合、リストをスクロールするのは難しいでしょう。

ネイティブパフォーマンスの改善

Kotlin 2.0.20では、Kotlin/NativeチームはiOSでのComposeアプリのパフォーマンスをより速く、よりスムーズにするために大きな進歩を遂げました。 Compose Multiplatform 1.7.3リリースでは、これらの最適化に加え、Jetpack Compose 1.7.0からのパフォーマンス改善も取り入れられています。

Kotlin 2.0.0と組み合わせたCompose Multiplatform 1.6.11と、Kotlin 2.0.20と組み合わせたCompose Multiplatform 1.7.3を比較すると、全体的に良い結果が見られます。

  • LazyGridベンチマークは、実際の使用例に最も近いLazyVerticalGridのスクロールをシミュレートし、平均して**約9%**高速に実行されます。 また、UIの応答性が低いとユーザーに感じさせる原因となるフレーム落ちの数も大幅に減少しています。 ぜひご自身でお試しください。Compose MultiplatformでiOS向けに作成されたアプリは、はるかにスムーズに感じるはずです。
  • VisualEffectsベンチマークは、多数のランダムに配置されたコンポーネントをレンダリングし、3.6倍高速に動作します。 1000フレームあたりの平均CPU時間は8.8秒から2.4秒に短縮されました。
  • AnimatedVisibilityコンポーザブルは、画像の表示と非表示をアニメーション化し、**約6%**高速なレンダリングを示します。

さらに、Kotlin 2.0.20では、ガベージコレクターに実験的な並行マーキングのサポートが導入されました。並行マーキングを有効にすると、ガベージコレクターの一時停止が短縮され、すべてのベンチマークでさらに大きな改善につながります。

これらのCompose固有のベンチマークのコードは、Compose Multiplatformリポジトリで確認できます。

デスクトップ

ドラッグ&ドロップ

ユーザーがコンテンツをComposeアプリケーションにドラッグしたり、アプリケーションからドラッグしたりできるようにするドラッグ&ドロップメカニズムが、デスクトップ版のCompose Multiplatformに実装されました。 ドラッグ&ドロップの潜在的なソースと宛先を指定するには、dragAndDropSourceおよびdragAndDropTarget修飾子を使用します。

これらの修飾子は共通コードで利用可能ですが、現在はデスクトップおよびAndroidソースセットでのみ動作します。 今後のリリースにご期待ください。

一般的な使用例については、Jetpack Composeドキュメントの専用記事を参照してください。

BasicTextField(BasicTextField2から名称変更)がデスクトップに採用されました

Jetpack ComposeはBasicTextField2コンポーネントを安定化させ、BasicTextFieldに名称変更しました。 このリリースでは、Compose Multiplatformがデスクトップターゲット向けにこの変更を採用しており、安定版1.7.0ではiOSもカバーする計画です。

新しいBasicTextFieldは以下の機能を提供します。

  • 状態をより確実に管理できます。
  • テキストフィールドのコンテンツをプログラムで変更するための新しいTextFieldBuffer APIを提供します。
  • 視覚的な変換とスタイリングのためのいくつかの新しいAPIが含まれています。
  • フィールドの以前の状態に戻る機能を持つUndoStateへのアクセスを提供します。

ComposePanelのレンダー設定

ComposePanelコンストラクタで新しいRenderSettings.isVsyncEnabledパラメータを指定することで、バックエンドレンダリング実装に垂直同期を無効にするようヒントを与えることができます。 これにより、入力とUIの変更間の視覚的な遅延を減らすことができますが、テアリングが発生する可能性もあります。

デフォルトの動作は変わりません。ComposePanelは描画可能なプレゼンテーションをVSyncと同期しようとします。

Web

skiko.jsはKotlin/Wasmアプリケーションにとって冗長になりました

skiko.jsファイルは、Compose MultiplatformでビルドされたKotlin/Wasmアプリケーションにとって冗長になりました。 index.htmlファイルから削除でき、アプリの読み込み時間を改善できます。 skiko.jsは将来のリリースでKotlin/Wasmの配布物から完全に削除されます。

skiko.jsファイルはKotlin/JSアプリケーションには依然として必要です。