Multiplatform

Compose Multiplatform 1.5.0 のリリース

Read this post in other languages:

Compose Multiplatform 1.5.0 をご利用いただけるようになりました。 これは Jetpack Compose の Kotlin 用宣言型 UI フレームワークを使用し、Android からデスクトップ、iOS、およびウェブに拡張するものです。 デスクトップバージョンは安定していますが、iOS バージョンはアルファ段階にあるためウェブのサポートは実験的です。 詳細は Compose Multiplatform ウェブサイトをご覧ください。

このリリースの主な改良点は次の通りです。

  1. Dialog、Popup、および WindowInsets API が共通コードに含まれるようになりました。
  2. iOS でスクロールする際のリソース管理とテキストフィールドが改善されました。
  3. デスクトップの UI テストフレームワークが安定化されました。

このリリースは Jetpack Compose 1.5 をベースにしており、パフォーマンスの改善に焦点が当てられています。 また、Material Design 3 の 1.1 リリースでビルドするようにもなっています。 このリリースには、日付ピッカーや時間ピッカーなどの新しいコンポーネントが含まれています。

Compose Multiplatform 1.5.0 を試す

Dialog、Popup、WindowsInsets をサポートする Compose Multiplatform

バージョン 1.5 より、Compose Multiplatform でダイアログとポップアップを使用できるようになりました。 ダイアログはユーザーに選択やデータの入力を促すモーダルイベントに使用されます。 一方、ポップアップはオプション機能の提供などの非モーダル動作に使用されます。

このリリースでは、基本型の DialogPopup、そして DropdownMenuAlertDialog に共通コードからアクセスできるようになっています。 これにより、プラットフォーム固有の機能を提供する必要性を回避しています。

たとえば、以下の Composable は完全に共通コードで記述されています。

これは、デスクトップ、Android、iOS で以下のように表示されます。

デスクトップにおけるダイアログボックスのデモ

Android と iOS におけるダイアログボックスのデモ

このリリースで提供を開始した 3 つ目の機能は、コンテンツとシステム UI が重なるのを防ぐのにどの程度の調整が必要かを表現する WindowInsets API です。 この機能はバージョン 1.5 から Compose Multiplatform に含まれており、Android と iOS の両方で使用することができます。

WindowInsets API を使用すると、Compose Multiplatform を介してノッチの背後に背景コンテンツを描画できます。 これは、アプリケーションの最上部に白い行を追加せずに行えます。 この違いを以下のスクリーンショットでご覧ください。

WindowInsets API を使用した Compose Multiplatform での背景コンテンツの描画

iOS での改善

このリリースは iOS プラットフォームに焦点が当てられており、さまざまな改善が行われています。 スクロール処理がこのプラットフォームと同様の見た目になり、リソース管理が単純化され、テキスト処理が強化されています。

自然なスクロール処理

このリリースでは、iOS のスクロール処理がネイティブのスクロール処理と同様になるように調整されています。 表示される項目の数やサイズが使用可能なスペースに収まらないコードがあるとしましょう。

スクロールすると、ネイティブの iPhone アプリケーションと同様に項目が画面の端から現われます。

iOS でスクロールした際の出現処理

Dynamic Type のサポート

iOS の Dynamic Type 機能を使うと、ユーザーが指定したフォントサイズ(閲覧しやすくする場合はさらに大きな文字、表示されるコンテンツの量を増やす場合はさらに小さな文字)を設定できます。 アプリ内で使用されるテキストのサイズは、このシステム設定に相対的なサイズとなります。

この機能が Compose Multiplatform でサポートされるようになりました。 テキストの拡大縮小にはネイティブアプリケーションと同じ変化量が使用されるため、動作はまったく変わりません。

たとえば、以下の Composable があるとします。

指定した閲覧サイズが最小に設定されている場合、以下のように表示されます。

Compose Multiplatform における iOS の Dynamic Type 機能(小さなテキスト)

一方、指定した閲覧サイズが最大である場合は以下のような結果になります。

Compose Multiplatform における iOS の Dynamic Type 機能(大きなテキスト)

高リフレッシュレートのディスプレイのサポート

以前のバージョンでは最大フレームレートが 60 FPS になっていました。 このため、120 Hz のディスプレイを搭載したデバイスでは UI の動作が重くなって遅延が発生することがありました。 このリリースからは最大 120 FPS のフレームレートがサポートされています。

リソース管理の単純化

1.5.0 以降、iOS ソースセットのリソースフォルダーに含まれるアセットはデフォルトでアプリケーションバンドルにコピーされます。 そのため、たとえば画像ファイルを src/commonMain/resources/ に配置すると、画像ファイルがバンドルにコピーされてコードで使用できるようになります。

CocoaPods を使用している場合、Gradle ビルドファイルでこの動作を構成する必要がなくなりました。 また、変更後にアセットがコピーされていることを確認するために podInstall をもう一度呼び出す必要もありません。

このリリースからは、ビルドスクリプトで明示的に動作を構成しようとするとエラーが発生します。

詳しい内容と既存コードの移行に関するガイドは、こちらのドキュメントをご覧ください

TextField の改善

以前のリリースでは、テキストを入力すると好ましくない状況が発生しうる状況が 2 つありました。 このリリースからは、それらの問題を克服するように TextField が強化されています。

大文字化の問題

まず、TextField が先頭文字の自動大文字化が無効になっていることを認識するようになりました。 これは、パスワードを入力する場合などには重要です。 この動作は keyboardOptions 引数で制御します。

分かりやすくするため、以下の Composable を使って説明します。

左の画像は大文字化のプロパティが KeyboardCapitalization.None に設定されている場合の動作を示し、右の画像は値が KeyboardCapitalization.Sentences である場合の動作を示しています。

TextField の大文字化のデモ

ハードウェアキーボード

2 つ目の状況はハードウェアキーボードに関連するものです。 以前のバージョンでは、ハードウェアキーボードを使用して Enter を押すと複数の改行が挿入され、Backspace を押すと複数の削除操作が行われていました。 このリリースからは、これらのイベントが正しく処理されるようになっています。

デスクトップの改善

テストフレームワークの安定化

このリリースでは、Compose for Desktop で安定したテストのサポートが提供されるようになりました。 Jetpack Compose は Compose コードの動作を検証するための一連のテスト API を提供しています。 これらの API は前のリリースでもデスクトップに移植されて使用可能でしたが、制限がありました。 その制限が撤廃され、アプリケーション用の UI テストを包括的に記述できるようになっています。

テスト機能の概要を知るため、簡単な UI を作成してテストしてみましょう。 以下はサンプルの Composable です。

これは、検索の試行内容を記録する単純な UI を作成しています。

テスト用の検索アプリ

Modifier.testTag を使って TextFieldButton、および LazyColumn の項目に名前が割り当てられていることに注目してください。

そして、この UI を JUnit テスト内で操作できます。

Compose 固有の JUnit ルールを使って以下を行います。

  1. UI のコンテンツをアプリの Composable として設定します。
  2. onNodeWithTag を使ってテキストフィールドとボタンの位置を特定します。
  3. サンプルの値をテキストフィールドに繰り返し入力し、ボタンをクリックします。
  4. onAllNodesWithTag を使って生成されたテキストノードをすべて検索します。
  5. 作成されたテキストノードの現在の数をアサートし、最後のノードを取得します。
  6. この最後の試行に期待されるメッセージが含まれることをアサートします。

Swing 相互運用機能の強化

このリリースでは、Swing コンポーネント内での Compose パネルのレンダリングを改善する実験的サポートが導入されました。 これにより、パネルが表示、非表示、またはサイズ変更された場合の暫定的なレンダリングに関する問題が回避されます。 また、Swing コンポーネントと Compose パネルを組み合わせた場合のレイヤー処理も適切に行われるようになりました。 Swing コンポーネントを ComposePanel の上下に表示できるようになっています。

分かりやすくするため、以下の例を使って説明します。

このコードでは、以下のコンテンツを含む Swing JFrame を作成して表示しています。

  1. JFrame には縦方向の区切り線のある JSplitPane が含まれます。
  2. 分割されたペインの左側はシアン色の標準の JPanel です。
  3. 右側は JLayeredPane で、以下の 2 つのレイヤーで構成されています。
    • Box Composable を含む黒色の ComposePanel
    • テキスト「Popup」が白い矩形内に表示されるカスタム Swing コンポーネント。 これは、paintComponent メソッドのオーバーライドによって実現されています。

プロパティ compose.swing.render.on.graphics が true に設定された場合:

  • カスタム Swing コンポーネントが Box Composable の上に表示されています。
  • スライダーを動かしても暫定的なグラフィックアーティファクトは現われません。

Swing 相互運用機能が有効な場合のデモ

このフラグが設定されていない場合はカスタムコンポーネントが表示されないため、スライダーを動かすと暫定的なアーティファクトが現われる可能性があります。

Swing 相互運用機能が無効な場合のデモ

Compose Multiplatform に関するフィードバックをお寄せください。 Kotlin Slack の #compose チャンネルで行われているディスカッションにご参加ください。Compose Multiplatform と Jetpack Compose に関連する一般的なトピックについて話し合うことができます。 #compose-ios では、Compose Multiplatform for iOS に関するディスカッションを参照できます。

Compose Multiplatform 1.5.0 を試す

その他の記事と動画

オリジナル(英語)ブログ投稿記事の作者:

Ryuji Owan

Garth Gilmour

image description

Discover more