💬
Jetpack Compose で背景画像を repeat させる
Android で背景画像を repeat させるには、以下のように実装します。[1]
tile_background.xml
<?xml version="1.0" encoding="utf-8"?>
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
android:antialias="true"
android:dither="false"
android:filter="false"
android:gravity="fill"
android:src="@android:drawable/alert_dark_frame"
android:tileMode="repeat" />
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/tile_background" />
ビルド結果は以下のようになります。
ですが、これを Jetpack Compose でやるとなった場合、残念ながら対応する Composable は用意されていません(2022 年 3 月 4 日時点)。
解決策
以下のように AndroidView
を用意して、その中で背景画像を repeat させるようにします。
TiledImage.kt
@Composable
fun TiledImage(
modifier: Modifier = Modifier,
@DrawableRes id: Int,
contentDescription: String? = null
) {
AndroidView(
modifier = modifier
.semantics {
contentDescription?.let {
this.contentDescription = it
}
},
factory = {
val bitmapDrawable = BitmapDrawable(it.resources, BitmapFactory.decodeResource(it.resources, id)).apply {
tileModeX = Shader.TileMode.REPEAT
tileModeY = Shader.TileMode.REPEAT
}
View(it).apply {
background = bitmapDrawable
}
}
)
}
@Preview(showBackground = true)
@Composable
private fun Preview() {
TiledImage(id = R.drawable.alert_dark_frame)
}
ポイントとしては、BitmapDrawable
を生成し、tileModeX
および tileModeY
に Shader.TileMode.REPEAT
を設定することです。
factory = {
val bitmapDrawable = BitmapDrawable(it.resources, BitmapFactory.decodeResource(it.resources, id)).apply {
tileModeX = Shader.TileMode.REPEAT
tileModeY = Shader.TileMode.REPEAT
}
View(it).apply {
background = bitmapDrawable
}
}
こちらは任意ですが、contentDescription
を設定してテストしやすいように実装するのがおすすめです。
// contentDescriptionを設定してテストしやすいように
modifier = modifier
.semantics {
contentDescription?.let {
this.contentDescription = it
}
}
プレビュー結果は以下のようになります。
もっとより良い方法がありましたらご指摘ください。
Discussion