Has anyone worked on Horizontal pager in compose w...
# android
b
Has anyone worked on Horizontal pager in compose with infinite scroll from both sides i cant get it to swipe left on the first item only, right items are fine
x
Can you paste an snippet with your current implementation?
b
yes sure
Copy code
@Stable
@OptIn(ExperimentalFoundationApi::class)
@Composable
fun TopCarouselPager(
    uiModule: UIModule?,
    modifier: Modifier = Modifier,
    contentModule: ContentModule,
    onTrayClick: (contentData: ContentData) -> Unit,
    watchList: ArrayList<String?>,
    onLoginClick: () -> Unit,

) {
    val items: List<ContentData> = contentModule.contentData ?: emptyList()
    val carouselImageSize = uiModule?.settings?.carouselImageSize ?: "3x4"
    val selectedItem = remember { mutableStateOf<ContentData?>(null) }
    var itemSpacing = 0.dp
    var contentPadding = 0.dp
    var paddingStart = 0.dp
    (carouselImageSize == "16x9" || carouselImageSize == "32x9").ifTrue {
        itemSpacing = 10.dp
        contentPadding = 50.dp
        paddingStart = 14.dp
    }
    items.isNotEmpty().ifTrue {
        val pagerState = rememberPagerState(
            initialPage = 0,
            initialPageOffsetFraction = 0f,
        ) {
            // provide pageCount
            Int.MAX_VALUE
        }
        HorizontalPager(
            state = pagerState,
            key = { page -> items[page.floorMod(items.size)].contentId },
            modifier = modifier.padding(start = paddingStart),
            pageSpacing = itemSpacing,
            contentPadding = PaddingValues(end = contentPadding),
            beyondBoundsPageCount = 1,
        ) { page ->
            val item = items[page.floorMod(items.size)]
            val isAddedToWatchList = watchList.contains(item.contentId)
            TopCarouselItem(
                item,
                isAddedToWatchList,
                carouselImageSize,
                onTrayClick,
                onLoginClick,
                onWatchListItemClick = {
                    if (it) {
                        watchList.add(item.contentId)
                    } else {
                        watchList.remove(item.contentId)
                    }
                },
                contentPadding + paddingStart,
            )

            // selectedPage = pagerState.currentPage % items.size
            selectedItem.value = item
        }
        AutoScrollPager(pagerState)
    }
}
x
It looks like that
AutoScrollPager
is the one managing the swipe logic. Can you paste the code in that function?
b
Copy code
@OptIn(ExperimentalFoundationApi::class)
@Stable
@Composable
fun AutoScrollPager(pagerState: PagerState) {
    val isDraggedState = pagerState.interactionSource.collectIsDraggedAsState()
    LaunchedEffect(isDraggedState) {
        snapshotFlow { isDraggedState.value }.collectLatest { isDragged ->
            if (!isDragged) {
                while (true) {
                    delay(10000L)
                    try {
                        pagerState.animateScrollToPage(pagerState.currentPage + 1)
                    } catch (ignore: IllegalStateException) {
                        ignore.printStackTrace()
                    }
                }
            }
        }
no auto AutoScrollPager is to automatically scroll the page
Copy code
fun Int.floorMod(other: Int): Int = when (other) {
    0 -> this
    else -> this - floorDiv(other) * other
}
this is the code of the
floorMod
x
It looks like you should be managing the index overflow or underflow in the
AutoScrollPager
function. This line seems suspicious to me:
Copy code
try {
    pagerState.animateScrollToPage(pagerState.currentPage + 1)
}
I like your use of
snapshotFlow
in that
AutoScrollPager
function
b
Okk
In Accompanist library it was there an option to have infinite scroll but now it is not present as it is depricated and migrated to compose.foundation.pager
Copy code
val pagerState = rememberPagerState(
    // the initial value is set high to manage both side infinite scrolling
    initialPage = (Int.MAX_VALUE/2)-(Int.MAX_VALUE/2%items.size),
    initialPageOffsetFraction = 0f,
) {
    // provide pageCount
    Int.MAX_VALUE
}
to manage that i did this so that the initial item will be much far and look like infinite
c
just remember if you do stuff like this to consider the accessibility impact 🐕‍🦺
b
Ya I am aware of that but i just for now kept like that and I am trying to find good implementation