16
13

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【Jetpack Compose】Preview をもっと簡単に増やしたい場合(PreviewParameter, Multipreview Annotations)

Posted at

はじめに

Preview をより簡単に増やせる方法を学んだので、それらを備忘録としてまとめていこうと思います。

この記事で分かること

  • @PreviewParameter の使い方
  • Multipreview Annotations の使い方

今回 Preview させるもの

単純にメモのリストを表示させるような、非常に簡単なもので試していきたいと思います。Loading 時には CircularProgressIndicator() を、Error 時には Dialog を表示させています。

@SuppressLint("UnusedMaterialScaffoldPaddingParameter")
@Composable
fun ExampleScreen(uiState: ExampleUiState) {
    Scaffold(
        topBar = {
            TopAppBar(
                title = { Text(text = "ExampleScreen") }
            )
        }
    ) {
        if (uiState.memos.isEmpty()) {
            Text(
                text = "まだメモがありません",
                modifier = Modifier.fillMaxSize().padding(top = 40.dp),
                textAlign = TextAlign.Center,
            )
        } else {
            MemoList(memos = uiState.memos)
        }

        if (uiState.isLoading) {
            Column(
                modifier = Modifier.fillMaxSize(),
                verticalArrangement = Arrangement.Center,
                horizontalAlignment = Alignment.CenterHorizontally
            ) {
                CircularProgressIndicator()
            }
        }

        if (uiState.isError) {
            Dialog(onDismissRequest = {}) {
                Column(
                    modifier = Modifier.size(300.dp, 200.dp).background(Color.White),
                    verticalArrangement = Arrangement.Center,
                    horizontalAlignment = Alignment.CenterHorizontally
                ) {
                    Text(text = "エラーです", color = Color.Black)
                }
            }
        }
    }
}

@Composable
fun MemoList(memos: List<Memo>) {
    LazyColumn(
        contentPadding = PaddingValues(horizontal = 16.dp),
        verticalArrangement = Arrangement.spacedBy(8.dp),
    ) {
        items(memos) { memo ->
            Text(text = memo.title)
        }
    }
}

簡略化のために Memotitle のみを持たせています。

data class ExampleUiState(
    val memos: List<Memo> = emptyList(),
    val isLoading: Boolean = false,
    val isError: Boolean = false
)

data class Memo(
    val title: String
)

単純にPreviewをさせる場合

以下のように、uiState の中身だけが異なる Preview が多発します。

// メモがない場合
@Preview
@Composable
fun Preview1() {
    ExampleTheme {
        ExampleScreen(
            uiState = ExampleUiState()
        )
    }
}

// メモがある場合
@Preview
@Composable
fun Preview2() {
    ExampleTheme {
        ExampleScreen(
            uiState = ExampleUiState(
                memos = List(50) { Memo(title = "タイトル No.$it") }
            )
        )
    }
}

// Loading 状態
@Preview
@Composable
fun Preview3() {
    ExampleTheme {
        ExampleScreen(
            uiState = ExampleUiState(
                memos = List(50) { Memo(title = "タイトル No.$it") },
                isLoading = true
            )
        )
    }
}

// Error状態
@Preview
@Composable
fun Preview4() {
    ExampleTheme {
        ExampleScreen(
            uiState = ExampleUiState(
                memos = List(50) { Memo(title = "タイトル No.$it") },
                isError = true
            )
        )
    }
}

最初は良くても増えてくると結構面倒になっていきます…。

@PreviewParameter を使用

そんな時に活用するのが @PreviewParamerter です。
まずは以下のようなクラスを作成しましょう。好きなだけ ExampleUiState を作ることが出来ます。

class FakeExampleUiStateProvider : PreviewParameterProvider<ExampleUiState> {
    override val values = sequenceOf(
        ExampleUiState(),
        ExampleUiState(
            memos = List(50) { Memo(title = "タイトル No.$it") }
        ),
        ExampleUiState(
            memos = List(50) { Memo(title = "タイトル No.$it") },
            isLoading = true
        ),
        ExampleUiState(
            memos = List(50) { Memo(title = "タイトル No.$it") },
            isError = true
        ),
        ExampleUiState(
            memos = List(50) {
                Memo(title = "長いタイトル長いタイトル長いタイトル長いタイトル長いタイトル長いタイトル No.$it")
            }
        )
    )
}

そして以下のように @PreviewParameter を使うだけで、先ほど作成した ExampleUiState を使うことが出来ます。

@Preview
@Composable
fun ExamplePreview(
    @PreviewParameter(FakeExampleUiStateProvider::class) uiState: ExampleUiState // ここ!
) {
    ExampleTheme {
        ExampleScreen(uiState = uiState)
    }
}

結果は以下の通りになります。
それぞれの Preview をわざわざ5つ書かなくても @PreviewParameter を使用すると簡単に表示出来て便利です。

image.png

これらをさらにLightモード、Nightモードの両方で確認したい場合があると思います。そんな際に便利なのが自分でアノテーションを作成する方法です。

Multipreview Annotations

以下にある通り、場合によっては使う事が出来ないので注意してください。

Note: This feature is available starting from Android Studio Dolphin and Jetpack Compose 1.2.0-beta01.(公式より)

まずは annotation class を作成し、

@Preview(
    name = "light mode",
    group = "ui modes",
    uiMode = UI_MODE_NIGHT_NO
)
@Preview(
    name = "night mode",
    group = "ui modes",
    uiMode = UI_MODE_NIGHT_YES
)
annotation class UiModePreviews

このアノテーションを表示したい Preview に付けるだけです。

@UiModePreviews // ここ!
@Composable
fun ExamplePreview(
    @PreviewParameter(FakeExampleUiStateProvider::class)
    uiState: ExampleUiState
) {
    ExampleTheme {
        ExampleScreen(uiState = uiState)
    }
}

これでLightモード・Nightモードの両方を確認できます。
image.png

参考資料

おわりに

上記の通り、これらを活用すればより簡単に Preview を表示できるので便利です!

ここまで読んでいただき、ありがとうございました!何かありましたら、コメントをお願いいたします。

16
13
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
16
13

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?