Compose Multiplatform でプラットフォーム固有のコンポーネントを表示する
前回の記事で、Compose Multiplatformを使って起動画面からホーム画面への画面遷移を実装した。詳細は以下の記事を参照して欲しい。
Compose Multiplatformとは
Compose Multiplatform(CMP)は、Kotlinを使ってAndroidとiOSの両方に対応したUIを構築するためのライブラリだ。同じコードベースから両方のプラットフォームに対応したアプリケーションを作成できる。CMPプロジェクトの作成方法やエミュレータでの実行方法については、以下の記事で詳しく紹介している。
開発環境
- MacBook Pro (16インチ, 2021)
- macOS Sonoma 14.5
- Xcode 15.4
- Android Studio Jellyfish | 2023.3.1 Patch 2
プラットフォームの世界観を守るために
以下の図のように、起動画面で実装したマテリアルデザインのインジケーターは、そのままiOSアプリとしてリリースするとユーザーに違和感を与える可能性がある。多くのユーザーにとって些事かもしれないが、私はiOSの世界観を守りたいと考えている。
Expected and actual declarations
の機能を使うと、iOSとAndroidそれぞれのプラットフォーム固有の実装ができる。この記事では、この機能を利用してプラットフォームに応じたUIコンポーネントの切り替え方法を紹介する。
外部ライブラリを追加する
前述の通り、Compose Multiplatformには標準でAndroid風のマテリアルデザインのコンポーネントが提供されているが、iOS風のコンポーネントは標準で用意されていない。そこで、alexzhirkevich/compose-cupertino
という外部ライブラリを利用する。
まずは、build.gradle.kts
ファイルに以下の依存関係を追加する。
kotlin { sourceSets { commonMain.dependencies { implementation("io.github.alexzhirkevich:cupertino:0.1.0-alpha04") // <--- Add implementation("io.github.alexzhirkevich:cupertino-adaptive:0.1.0-alpha04") // <--- Add } } }
ファイルを追加する
Kotlin Multiplatformでは、expect
とactual
キーワードを使用して、プラットフォームごとの具体的な実装を提供できる。これにより、共通のコードをプラットフォームに依存しない形で書き、特定のプラットフォームに特有の実装を提供できる。それぞれのファイルの実装を見ていこう。
まず、expect
とactual
を実装するファイルを追加する。commonMain
にProgressIndicator.kt
、iosMain
にProgressIndicator.ios.kt
、androidMain
にProgressIndicator.android.kt
を追加する。
expect キーワード
expect
キーワードは共通コードで宣言され、特定のプラットフォームで実装されることを期待する宣言だ。共通モジュール(commonMain)で定義され、ここでは実際のViewを実装しない。
import androidx.compose.runtime.Composable @Composable expect fun ProgressIndicator()
actual キーワード
actual
キーワードは、expect
宣言に対する具体的なプラットフォーム固有の実装を提供するために使用される。これは、各プラットフォームモジュール(androidMainやiosMainなど)で定義される。
androidMain
のProgressIndicatorでは、CircularProgressIndicator
を利用する。
import androidx.compose.material.CircularProgressIndicator import androidx.compose.runtime.Composable @Composable actual fun ProgressIndicator() { CircularProgressIndicator() }
最後に、iosMain
のProgressIndicatorでは、導入したライブラリのCupertinoActivityIndicator
を利用する。
import androidx.compose.runtime.Composable import androidx.compose.ui.unit.dp import io.github.alexzhirkevich.cupertino.CupertinoActivityIndicator import io.github.alexzhirkevich.cupertino.ExperimentalCupertinoApi @OptIn(ExperimentalCupertinoApi::class) @Composable actual fun ProgressIndicator() { CupertinoActivityIndicator( size = 24.dp, ) }
iOSシミュレータで実行すると、下図のようにiOSではUIActivityIndicatorView風のインジケーターが表示されるようになった。
以上の手順で、Compose Multiplatformを使ってiOSスタイルのプログレスインジケーターを実装できた。これでiOSアプリを使っているユーザーが違和感を感じなければ嬉しい。