- (擬似的に)無限ループしたい
- タップされているときは自動送りしない
private const val PAGE_COUNT = 10_000
private const val INITIAL_PAGE = PAGE_COUNT / 2
private fun Int.floorMod(other: Int): Int = when (other) {
0 -> this
else -> this - this.floorDiv(other) * other
}
@Composable
fun AutoScrollHorizontalPager(
itemSize: Int,
modifier: Modifier = Modifier,
autoScrollDuration: Long = 2_000L,
onPageChanged: ((page: Int) -> Unit)? = null,
pageContent: @Composable PagerScope.(page: Int) -> Unit,
) {
val pagerState = rememberPagerState(INITIAL_PAGE) { PAGE_COUNT }
fun Int.toIndex(): Int = (this - INITIAL_PAGE).floorMod(itemSize)
if (onPageChanged != null) {
LaunchedEffect(onPageChanged) {
snapshotFlow { pagerState.currentPage }
.collect { page -> onPageChanged(page.toIndex()) }
}
}
val dragged by pagerState.interactionSource.collectIsDraggedAsState()
if (!dragged) {
LaunchedEffect(Unit) {
while (true) {
delay(autoScrollDuration)
val nextPage = pagerState.currentPage + 1
if (nextPage < PAGE_COUNT) {
pagerState.animateScrollToPage(nextPage)
} else {
pagerState.scrollToPage(0)
}
}
}
}
HorizontalPager(
state = pagerState,
modifier = modifier,
) { page ->
pageContent(page.toIndex())
}
}