Jetpack Compose で Coil を利用して画像を表示する方法まとめ
はじめに
Jetpack Compose でアプリを作成している際に Coil を利用して画像を表示する方法をまとめます。
セットアップ
build.gradle(app)
に以下の内容を記述してcoil-compose
をインストールする。
dependencies {
︙
implementation("io.coil-kt:coil-compose:1.4.0")
︙
}
また今回のサンプルではネットワーク経由で画像を取得するのであればパーミッションを追加しておきます。(また暗号化されていないHTTP 通信経由で画像を取得するのであれば cleartextTrafficPermitted
も true
にしておく必要があります。)
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="jp.kaleidot725.sample">
<uses-permission android:name="android.permission.INTERNET" />
<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.Sample"
android:usesCleartextTraffic="true"
tools:targetApi="31">
︙
</application>
</manifest>
Coil で画像を読み込む
rememberImagePainter
で ImagePainter
を生成し、Image の painter にセットするだけで画像を読み込める。
@Composable
fun SimpleImage() {
val imageUrl = "https://developer.android.com/images/brand/Android_Robot.png"
Image(
painter = rememberImagePainter(imageUrl),
contentDescription = null
)
}
ちなみに生成した ImagePainter
には State
というプロパティが定義されており、State
を確認することで画像の取得の成否が確認できるようになっている。なので画像が取得できないなど不具合に遭遇した場合には State
を確認すれば原因を突き止められる。
@Composable
fun StateCheckImage() {
val imageUrl = "https://developer.android.com/images/brand/Android_Robot.png"
val painter = rememberImagePainter(imageUrl)
Image(
painter = painter,
contentDescription = null,
modifier = Modifier.size(128.dp)
)
Log.v("TEST", "${painter.state}")
}
State
とは ImagePainter
クラスに定義される enum class のことで以下のように Empty
Loading
Success
Error
の4種類の状態が定義されている。
@ExperimentalCoilApi
sealed class State {
/** The current painter being drawn by [ImagePainter]. */
abstract val painter: Painter?
/** The request has not been started. */
object Empty : State() {
override val painter: Painter? get() = null
}
/** The request is in-progress. */
data class Loading(
override val painter: Painter?,
) : State()
/** The request was successful. */
data class Success(
override val painter: Painter,
val result: SuccessResult,
) : State() {
@Deprecated(
message = "Migrate to `result.metadata`.",
replaceWith = ReplaceWith("result.metadata")
)
val metadata: ImageResult.Metadata get() = result.metadata
}
/** The request failed due to [ErrorResult.throwable]. */
data class Error(
override val painter: Painter?,
val result: ErrorResult,
) : State() {
@Deprecated(
message = "Migrate to `result.throwable`.",
replaceWith = ReplaceWith("result.throwable")
)
val throwable: Throwable get() = result.throwable
}
}
画像を読み込むときにクロスフェードする
crossfade
を true
にするとクロスフェードするようにできる。
@Composable
fun CrossFadeImage() {
val imageUrl = "https://developer.android.com/images/brand/Android_Robot.png"
Image(
painter = rememberImagePainter(
data = imageUrl,
builder = {
crossfade(true)
}
),
contentDescription = null
)
}
画像を読み込むときにクロスフェードの秒数(ms)を指定する
crossfade
には Int
でどれぐらいの間隔でクロスフェードするか指定できる。
@Composable
fun CrossFadeMsImage() {
val imageUrl = "https://developer.android.com/images/brand/Android_Robot.png"
Image(
painter = rememberImagePainter(
data = imageUrl,
builder = {
crossfade(3000)
}
),
contentDescription = null
)
}
プレースホルダー画像を設定する
placeholder
にて指定した URL の画像の読み込みが完了する前のプレースホルダー画像を drawable
リソースから指定できる。
@Composable
fun ImageWithPlaceHolder() {
val imageUrl = "https://developer.android.com/images/brand/Android_Robot.png"
Image(
painter = rememberImagePainter(
data = imageUrl,
builder = {
placeholder(R.drawable.placeholder)
}
),
contentDescription = null
)
}
エラー画像を設定する
error
にて指定した URL の画像の読み込みに失敗したときのエラー画像を drawable
リソースから指定できる。
@Composable
fun ImageWithError() {
val imageUrl = "https://developer.android.com/images/brand/Android_Robot.png"
Image(
painter = rememberImagePainter(
data = imageUrl,
builder = {
error(R.drawable.error)
}
),
contentDescription = null
)
}
読み込む画像を加工する
Coiil では Blur
CircleCrop
Grayscale
RoundedCorner
の4種類の加工ができる
Blur
ガウシアンフィルターをかけてぼかしが効いた画像に加工できる。
@Composable
fun BlurImage() {
val imageUrl = "https://developer.android.com/images/brand/Android_Robot.png"
Image(
painter = rememberImagePainter(
data = imageUrl,
builder = {
transformations(BlurTransformation(LocalContext.current))
}
),
contentDescription = null
)
}
CircleCrop
円形にクロッピングした画像に加工できる。
@Composable
fun CircleImage() {
val imageUrl = "https://developer.android.com/images/brand/Android_Robot.png"
Image(
painter = rememberImagePainter(
data = imageUrl,
builder = {
transformations(CircleCropTransformation())
}
),
contentDescription = null
)
}
GrayScale
グレースケールに画像を加工できる。
@Composable
fun GrayScaleImage() {
val imageUrl = "https://developer.android.com/images/brand/Android_Robot.png"
Image(
painter = rememberImagePainter(
data = imageUrl,
builder = {
transformations(GrayscaleTransformation())
}
),
contentDescription = null
)
}
Rounded Corner
角を丸めた画像に加工できる。
@Composable
fun RoundedCornerImage() {
// Photo by <a href="https://unsplash.com/@gcoppa?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Guido Coppa</a> on <a href="https://unsplash.com/s/photos/android?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Unsplash</a>
val imageUrl = "https://images.unsplash.com/photo-1580860749755-f49eb5509d55?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2874&q=80"
Image(
painter = rememberImagePainter(
data = imageUrl,
builder = {
transformations(RoundedCornersTransformation(topLeft = 128f, topRight = 128f, bottomLeft = 128f, bottomRight = 128f))
}
),
contentDescription = null
)
}
Discussion