[Compose Multiplatform]Libresで画像リソースをアプリに組み込んで表示する方法
はじめに
調べたところどうやらCompose Multiplatform(v1.4.1)で画像リソースを組み込む際はLibresやmoko-resourcesというサードパーティ製のライブラリを利用するのが一般的な手法らしいです。今回はLibresというライブラリを利用して画像リソースをアプリに組み込む方法について調べたのでやり方をまとめて解説していきます。
Libresとは?
Libresは画像リソースや文字列リソースからAndroid・iOS・MacOSの各アプリで取り扱えるリソースクラスを作成してくれるライブラリです。
例えば以下のようにプロジェクトフォルダに画像リソースや文字列リソースを格納しておくと、この画像リソースや文字列リソースから以下のようなリソースクラスを生成してくれるらしいです。
プロジェクトフォルダ
.
└── commonMain
├── kotlin
└── libres
├── images
│ └── star_(orig).svg
└── strings
├── strings_en.xml
└── strings_ja.xml
リソースクラス
public object MainRes {
public val string: MainResStrings = MainResStrings
public val image: MainResImages = MainResImages
}
@OptIn(ExperimentalObjCName::class)
public object MainResStrings {
private val baseLocale: StringsJa = StringsJa
private val locales: Map<String, Strings> = mapOf("en" to StringsEn, "ja" to StringsJa)
@ObjCName(name = "helloWorld")
public val hello_world: String
get() = locales[getCurrentLanguageCode()]?.hello_world ?: baseLocale.hello_world
@ObjCName(name = "helloUsername")
public val hello_username: HelloUsername
get() = locales[getCurrentLanguageCode()]?.hello_username ?: baseLocale.hello_username
}
public expect object MainResImages {
public val star: Image
}
生成されたリソースクラスはImage
とText
のコンポーザブル関数と連携できるように生成されるので、以下のようなコードで画像リソースや文字列リソースをImage
やText
に渡して表示すること可能になります。
サンプルコード
@Composable
internal fun App() = AppTheme {
Box(modifier = Modifier.fillMaxSize()) {
Column(modifier = Modifier.wrapContentSize().align(Alignment.Center)) {
Image(
painter = MainRes.image.star.painterResource(),
contentDescription = "star",
modifier = Modifier.size(32.dp)
)
Text(text = MainRes.string.hello_world)
Text(text = MainRes.string.hello_username.format("Katz"))
}
}
}
Libresを使ってみる
今回はLibresを使って画像リソースをアプリに組み込んでいきます。Libresを利用して画像リソースをアプリに組み込むためには以下の3ステップで作業を進めていきます。
- セットアップ
- Libresが生成するリソースクラスに画像リソースを含める
- Libresが生成したリソースクラスを使って画像を表示する
1. セットアップ
まずはLibresの依存関係のセットアップから始めていきます。Compose Multiplatformのプロジェクトを作成した後に、以下のコードを各ファイルに記述してLibresの依存関係をセットアップします。
libs.version.toml
// VersionCatalogにLibresのプラグイン・ライブラリの依存関係の情報を登録していく。
[versions]
︙ 省略
libres = "1.1.8"
︙ 省略
[libraries]
︙ 省略
libres = { module = "io.github.skeptick.libres:libres-compose", version.ref = "libres" }
︙ 省略
[plugins]
︙ 省略
libres = { id = "io.github.skeptick.libres", version.ref = "libres" }
︙ 省略
build.gradle.kts(AppName)
// プロジェクトのルートの`build.gradle.kts(AppName)`にLibresのプラグインの依存関係を登録する。
plugins {
alias(libs.plugins.multiplatform).apply(false)
alias(libs.plugins.compose).apply(false)
alias(libs.plugins.cocoapods).apply(false)
alias(libs.plugins.android.application).apply(false)
alias(libs.plugins.libres).apply(false)
}
build.gradle.kts(:composeApp)
// プロジェクトのアプリの`build.gradle.kts(:composeApp)`にLibresのプラグインとライブラリの依存関係を追加する。
plugins {
alias(libs.plugins.libres)
}
sourceSets {
val commonMain by getting {
dependencies {
implementation(libs.libres)
}
}
}
// 更に`build.gradle.kts(:composeApp)`にはLibresのデータリソースの生成の設定を記述しておく。`libres`の`generatedClassName`で生成するリソースクラス名を決められるようになっているので、`MainRes`と指定して`MainRes`でリソースクラスを参照できるようにしておく。
libres {
generatedClassName = "MainRes"
}
2. Libresが生成するリソースクラスに画像リソースを含める
次にリソースクラスに画像リソースを含める作業をしていきます。リソースクラスに画像リソースを含める作業は簡単でComposeApp
のcommonMain
にlibres/images
フォルダを作成して、そこに画像リソースを格納してあげるだけです。これでLibresがリソースクラスに画像リソースを含めてくれるようになります。
// 今回はスター画像(SVG)を画像リソースとして用意して、star_(org).svgというファイル名称で`libres/iamges`フォルダへ格納することにしました。
└── commonMain
├── kotlin
└── libres
└── images
└── star_(orig).svg
3. Libresが生成したリソースクラスを使って画像を表示する
次に生成されたリソースクラスを利用して画像リソースをImage
で表示するための作業をしていきます。手順2の作業が終わってビルドをするとMainRes
というクラス名でリソースクラスが生成されているはずです。
public object MainRes {
public val string: MainResStrings = MainResStrings
public val image: MainResImages = MainResImages
}
@OptIn(ExperimentalObjCName::class)
public object MainResStrings
public expect object MainResImages {
public val star: Image
}
この生成されたMainRes
クラスを利用し、以下のようなコードでImage
に画像リソースを渡してあげれば、画像リソースを表示できます。
@Composable
internal fun App() = AppTheme {
Box(modifier = Modifier.fillMaxSize()) {
Image(
painter = MainRes.image.star.painterResource(),
contentDescription = "star",
modifier = Modifier.size(128.dp).align(Alignment.Center)
)
}
}
動作確認
最後にこのコードをビルドして動作確認してみましょう。このようにAndroid・iOSのアプリのそれぞれでアプリでビルドして起動すると、組み込んだ画像リソースが無事表示できていますね。
おわりに
このようにLibresを利用すると画像リソースを簡単に組み込むことが可能です。本記事のコードを実装したプロジェクトは以下にありますので興味がある方は御覧ください。
Discussion