androidandroid-viewpagerandroid-jetpack-compose

How to create an endless Pager in Jetpack Compose


    Box(
        modifier = Modifier.size(100.dp),
        contentAlignment = Alignment.Center
    ) {
        val pagerState = rememberPagerState()
        val items = listOf("A", "B", "C")
        androidx.compose.foundation.pager.HorizontalPager(
            state = pagerState,
            pageCount = items.size,
            modifier = Modifier,
            verticalAlignment = Alignment.CenterVertically
        ) { page ->
            Text(
                text = items[page],
                modifier = Modifier
            )
        }
    }

In the above code, the pager stops scrolling after reaching the last item. However, I want the pager to continue scrolling endlessly after reaching the last item.

sketch


Solution

  • You can create it by setting pageCount to Int.MAX_VALUE and getting modulus of current page to get index for your list of items.

    @Preview
    @Composable
    private fun Test() {
    
        val pageCount = Int.MAX_VALUE
        val items = listOf("A", "B", "C")
        val pagerState = rememberPagerState(
            initialPage = pageCount / 2
        )
    
        HorizontalPager(
            modifier = Modifier.fillMaxWidth(),
            pageCount = pageCount,
            state = pagerState
        ) {
             Text(text = items[it % 3])
        }
    }
    

    Edit

    As of Compose version 1.6.0 Int.MAX_VALUE(2147483647) causes pager to have ANR, to prevent this add a big number but smaller than 2147483647 that user won't bother to scroll that far.

    @Preview
    @Composable
    private fun InfinitePagerSample() {
        Column(
            modifier = Modifier
                .fillMaxSize()
                .padding(16.dp)
                .border(2.dp, Color.Red)
        ) {
    
            val items = remember {
                listOf("A", "B", "C")
            }
            val pageCount = items.size * 400
    
            val pagerState = rememberPagerState(
                initialPage = pageCount / 2,
                pageCount = {
                    pageCount
                }
            )
    
            HorizontalPager(
                modifier = Modifier.fillMaxWidth(),
                state = pagerState,
                beyondBoundsPageCount = 1
            ) {
    
                val color = if (it % items.size == 0) {
                    Color.Red
                } else if (it % items.size != 1) {
                    Color.Yellow
                } else Color.Green
    
                Column(modifier = Modifier.fillMaxSize().background(color)) {
                    SideEffect {
                        println("Page $it, composing...")
                    }
    
                    Text(text = items[it % 3], modifier = Modifier.fillMaxSize(), fontSize = 70.sp)
    
                }
            }
        }
    }