Jetpack Compose の Preview では複数パターンの場合分けを同一の Preview で表示できるように、引数を外部からとして渡すことができる PreviewParameterProvider があるのは周知のとおりです。
ただ、いままでこれで表示された各ケースは Preview のラベルは自動で表示される連番となってしまい、IDE 上ではどういうケースの Preview なのかがわかりづらいという課題がありました。
Compose 1.10.0 からは getDisplayName というメソッドが用意されているので、これをオーバーライドすることで、IDE 上でどのケースの Preview かを区別しやすくなっています:
サンプル
まず、サンプルコードを使って、PreviewParameterProvider を使って今までどのように表示されていたかをみていきましょう。
@Composable
fun MyName(
name: String,
modifier: Modifier = Modifier,
) {
Text(
text = "Hello $name!",
modifier = modifier
)
}
このような、すごく単純な Composable に対して、以下のような Preview を書くことができました:
@Preview
@Composable
fun MyNamePreview(
@PreviewParameter(MyNameProvider::class) name: String,
) {
MyName(name = name)
}
class MyNameProvider : CollectionPreviewParameterProvider<String>(
listOf("Android", "アンドロイド", "12345"),
)
この Preview はこのように表示されます:
name 0, name 1, ... と表示されているので、どういった意図で用意されたケースかは明確になっていません。それぞれが「アルファベット」「カタカナ」「数字」のときの表示を確認するという意図はここからは分かりづらいです。
ラベルを表示できるようにしてみる
ここで getDisplayName をオーバーライドしてラベルを返すようにしてみます:
@Preview
@Composable
fun MyNamePreview(
@PreviewParameter(MyNameProvider::class) params: Pair<String, String>,
) {
val (_, name) = params
MyName(name = name)
}
class MyNameProvider : CollectionPreviewParameterProvider<Pair<String, String>>(
listOf(
"アルファベット" to "Android",
"カタカナ" to "アンドロイド",
"数字" to "12345",
),
) {
override fun getDisplayName(index: Int): String? {
return values.elementAt(index).first
}
}
こうすれば、各 Preview についてどういうケースを意図した Preview なのかが自明になり把握しやすくできます:
ただ、CollectionPreviewParameterProvider をつかうがために、Pair<String, String> にして destructuring をしているのはちょっとカッコ悪いので…
@Preview
@Composable
fun MyNamePreview(
@PreviewParameter(MyNameProvider::class) name: String,
) {
MyName(name = name)
}
class MyNameProvider: PreviewParameterProvider<String> {
private val params = mapOf(
"アルファベット" to "Android",
"カタカナ" to "アンドロイド",
"数字" to "12345",
)
override val values: Sequence<String> = params.values.asSequence()
override fun getDisplayName(index: Int) = params.keys.elementAt(index)
}
このようにして、素の PreviewParameterProvider をつかってあげるほうがよっぽどか素直でみやすいかとは思います。
共通化
しかしながら、こういったケースごとに毎回実装するのは冗長なので、あらかじめ、このようにラベルを Pair でわたせる LabeledPreviewParameterProvider<T> のような実装を用意しておくのも便利でしょう:
class MyNameProvider: LabeledPreviewParameterProvider<String>(
"アルファベット" to "Android",
"カタカナ" to "アンドロイド",
"数字" to "12345",
)
open class LabeledPreviewParameterProvider<T>(
private vararg val params: Pair<String, T>,
): PreviewParameterProvider<T> {
override val values: Sequence<T> = params.asSequence().map { it.second }
override fun getDisplayName(index: Int) = params.elementAt(index).first
}
以上です!

