LoginSignup
2
3

More than 1 year has passed since last update.

Jetpack Composeで自動スクロールするカルーセルを実装する

Last updated at Posted at 2022-12-13

Jetpack Compose の Pager を使って自動で動くカルーセルを実装するときの例になります。
(Jetpack Compose BOM 2022.12.00 & Accompanist v0.28.0 での実装です)

実装例

@Composable
fun rememberAutoScrollPagerState(
    interval: Long,
    initialPage: Int = 0,
): PagerState {
    val lifecycleOwner = LocalLifecycleOwner.current
    val pagerState = rememberPagerState(initialPage = initialPage)
    var refreshCount by remember { mutableStateOf(0) }
    val isScrolling = pagerState.isScrollInProgress

    LaunchedEffect(refreshCount) {  // ③
        runCatching {
            val target = pagerState.currentPage + 1
            pagerState.animateScrollToPage(
                if (target >= pagerState.pageCount) {
                    0
                } else {
                    target
                }
            )
        }
    }
    LaunchedEffect(isScrolling) { // ①
        lifecycleOwner.repeatOnLifecycle(Lifecycle.State.RESUMED) {
            if (!isScrolling) {
                delay(interval)
                refreshCount++  // ②
            }
        }
    }
    return pagerState
}

このような Composable 関数を用意しておき、あとは Pager を実装する時に組み込むだけです。

@Composable
fun CarouselBanners(
    modifier: Modifier = Modifier,
) {
    // Line this
    val state = rememberAutoScrollPagerState(
        interval = 2000,
    )
    HorizontalPager(
        count = 10,
        state = state,
        modifier = modifier,
    ) { index ->
        Item(...)
    }
}

解説

① の LaunchedEffect でスワイプによる移動やコードからのページ送りがされたタイミングで処理が呼ばれるようにして、② でページ送りがされてスクロールが停止したタイミングでページ送りの処理をトリガーさせます。
トリガーされたページ送りの処理を ③ の LaunchedEffect が処理して実際にページを移動させます。
LaunchedEffect を 1 つだけで制御しようとすると LaunchedEffect に渡す key が変わると内部の処理がキャンセルされる挙動のおかげで animateScrollToPage が途中でキャンセルされたりするため、スクロールの処理とページ移動のトリガーを分離する必要があります。


LaunchedEffect はシンプルが故に少しのパズルが必要になる場合がありますが、 駆使することでこのような自動で動くカルーセルも簡単に実装できます。

2
3
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
2
3