開発ブログ

株式会社Nextatのスタッフがお送りする技術コラムメインのブログ。

電話でのお問合わせ 075-744-6842 ([月]-[金] 10:00〜17:00)

  1. top >
  2. 開発ブログ >
  3. Kotlin >
  4. 【Compose Multiplatform】Resourcesライブラリを用いたリソース取得のマルチプラットフォーム対応

【Compose Multiplatform】Resourcesライブラリを用いたリソース取得のマルチプラットフォーム対応

logo.pngみなさんこんにちは。今回はCompose Multiplatform記事の8回目になります。
画像やテキスト、フォントなどのリソース取得をマルチプラットフォーム対応させる「Resources」ライブラリを使ってみましょう。

これまでのCompose Multiplatform記事はこちら

Compose Multiplatform入門(環境構築編)
Compose Multiplatform入門(プロジェクト作成編)
Compose Multiplatform入門(画面遷移編)
Compose Multiplatform入門(ロギング編)
KMPAuthを使用したFirebaseソーシャルログイン(Android編)
KMPAuthを使用したFirebaseソーシャルログイン(iOS編)
Ktorを使用したHTTP通信とRepositoryの実装

マルチプラットフォーム対応のリソース取得処理

Compose Multiplatformでのリソース取得には、Resourcesライブラリを使用します。 今回はResourcesライブラリを用いて、画像表示処理を行います。

導入

build.gradle.ktsの更新


kotlin {
    sourceSets {
        commonMain.dependencies {
            implementation(compose.components.resources)
        }
    }
}

使用する画像のインポート

画像を配置する場所は、composeApp/src/commonMain/composeResources/drawable ディレクトリ内です。
今回は150x150.png という名前の画像ファイルを配置しました。
サポートしている画像ファイルは以下になります。
  • PNG
  • JPG
  • BMP
  • WEBP
  • XML形式のベクター画像
drawable.png
この時点で、一旦プロジェクトをビルドしてみましょう。
composeApp/build/generated/compose/resourceGenerator 内のDrawable0.kt というファイルに Res.drawable._150x150 という変数が自動生成されています。これを実装する側のコードでも参照していきます。
以下は自動生成されたDrawable0.kt内のコードを抜粋しています。

@ExperimentalResourceApi
private object Drawable0 {
  public val _150x150: DrawableResource by 
      lazy { init__150x150() }
}

@ExperimentalResourceApi
internal val Res.drawable._150x150: DrawableResource
  get() = Drawable0._150x150

@ExperimentalResourceApi
private fun init__150x150(): DrawableResource = org.jetbrains.compose.resources.DrawableResource(
  "drawable:_150x150",
    setOf(
      org.jetbrains.compose.resources.ResourceItem(setOf(), "drawable/150x150.png"),
    )
)

画像の表示

今回はこれまでの記事で使ってきたプロジェクトのHomeScreenに直接画像を表示してみます。
画像表示の処理を一行追加するだけです。

HomeScreen.kt の更新


package ui.screens.home

import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.material.Button
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import cafe.adriel.voyager.core.registry.rememberScreen
import cafe.adriel.voyager.core.screen.Screen
import cafe.adriel.voyager.koin.getScreenModel
import cafe.adriel.voyager.navigator.LocalNavigator
import cafe.adriel.voyager.navigator.currentOrThrow
import com.mmk.kmpauth.firebase.google.GoogleButtonUiContainerFirebase
import com.mmk.kmpauth.uihelper.google.GoogleSignInButton
import dev.gitlive.firebase.auth.FirebaseUser
import kotlinprojecttest.composeapp.generated.resources.Res
import kotlinprojecttest.composeapp.generated.resources._150x150
import org.jetbrains.compose.resources.ExperimentalResourceApi
import org.jetbrains.compose.resources.painterResource
import ui.screens.Screens

class HomeScreen : Screen {

    @OptIn(ExperimentalResourceApi::class)
    @Composable
    override fun Content() {
        val viewModel: HomeScreenViewModel = getScreenModel<HomeScreenViewModel>()
        val navigator = LocalNavigator.currentOrThrow

        Column(
            modifier = Modifier.fillMaxWidth(),
            horizontalAlignment = Alignment.CenterHorizontally
        ) {
            val anotherScreen = rememberScreen(Screens.Another(postId = "dummy_post_id"))

            Button(onClick = { navigator.push(anotherScreen) }) {
                Text("画面遷移")
            }

            var signedInUserName: String by remember { mutableStateOf("") }
            val onFirebaseResult: (Result<firebaseuser?>) -> Unit = { result ->
                if (result.isSuccess) {
                    val firebaseUser = result.getOrNull()
                    signedInUserName =
                        firebaseUser?.displayName ?: firebaseUser?.email ?: "不明なユーザー"
                } else {
                    signedInUserName = "サインインしていません"
                    println("Error Result: ${result.exceptionOrNull()?.message}")
                }

            }
            
            // 追加部分
            Image(painterResource(Res.drawable._150x150), null)

            GoogleButtonUiContainerFirebase(onResult = onFirebaseResult) {
                GoogleSignInButton(modifier = Modifier.fillMaxWidth()) { this.onClick() }
            }

            Text(
                text = signedInUserName,
            )
        }
    }
}

実行

Android, iOS両方で実行してみましょう。別々のプラットフォームで問題なく画像が表示できるのが確認できれば成功です。
resources_android.png
resources_ios.png

テキストリソースの取得

composeResources/values/strings.xml ファイルを用意して、中にテキスト情報を書き込めば、似たような処理でテキストの取得が可能になります。 これで設定の共通化にも役立てることができます。

strings.xml


<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="test">テスト文字列</string>
</resources>

呼び出し方


// UIで呼び出すとき
stringResource(Res.string.test)

// 内部処理で呼び出すとき
getString(Res.string.test)

さいごに

今回でCompose Multiplatformの記事連載は一旦終了になります。
Compose Multiplatformを扱うすべての方の一助になれば幸いです。
これからもバージョンアップなどで気になる機能が出てきた場合には記事を更新しようかと思いますので、よろしくお願いいたします。
  • posted by りっちゃん
  • Kotlin
TOPに戻る