Jetpack Compose の Pager を使って自動で動くカルーセルを実装するときの例になります。
(Jetpack Compose BOM 2022.12.00 & Accompanist v0.28.0 での実装です)
![](https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F126298%2F299ffaab-02bd-2006-9f2e-d91c468eccb8.gif?ixlib=rb-4.0.0&auto=format&gif-q=60&q=75&s=f2ac507846701ee92da50ee973bcdfd9)
実装例
@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
はシンプルが故に少しのパズルが必要になる場合がありますが、 駆使することでこのような自動で動くカルーセルも簡単に実装できます。