Image offset in Android TV auto-slider (Jetpack Compose)

210 Views Asked by At

The first image of the slider works fine, but from the second on it seems so that the images are not centered, and the second one seems to displace the first one, the third one displaces the first and second and so on.

The other problem is that when the slider comes to an end, instead of coming back to the first image, it goes to the third one.

Here is my code for both the image and the autoslider:

@Composable
fun SliderImage(
    @DrawableRes drawable: Int,
    @StringRes text: Int,
    modifier: Modifier = Modifier
) {
    Column(
        horizontalAlignment = Alignment.CenterHorizontally,
        verticalArrangement = Arrangement.Center,
        modifier = modifier.fillMaxWidth().fillMaxHeight()
    ) {
        Text(
            text = stringResource(text),
            modifier = Modifier.paddingFromBaseline(top = 24.dp, bottom = 8.dp),
            style = MaterialTheme.typography.bodyMedium
        )
        Image(
            painter = painterResource(drawable),
            contentDescription = null,
            contentScale = ContentScale.FillBounds,
            modifier = Modifier
                //.size(250.dp)

        )

    }
}
@OptIn(ExperimentalFoundationApi::class)
@Composable
fun AutoSlidingCarousel(
 modifier: Modifier = Modifier,
 alignment: Alignment = Alignment.Center,
 autoSlideDuration: Long = AUTO_SLIDE_DURATION,
 itemsCount: Int,
pagerState: PagerState = remember { PagerState() },
 itemContent: @Composable (index: Int) -> Unit
) {
LaunchedEffect(pagerState.currentPage) {
    delay(autoSlideDuration)
    pagerState.animateScrollToPage((pagerState.currentPage+1) % itemsCount)
}
    Box (
        modifier = modifier.fillMaxWidth(),
        contentAlignment = alignment
    ) {
        HorizontalPager(pageCount = itemsCount, state = pagerState) { page ->
            itemContent(page)
        }

        Surface(
            modifier = Modifier
                .padding(bottom = 8.dp)
                .align(Alignment.BottomCenter),
            shape = CircleShape,
            color = Color.Black.copy(alpha = 0.5f)
        ) {
            DotsIndicator(
                modifier = Modifier.padding(horizontal = 8.dp, vertical = 6.dp),
                totalDots = itemsCount,
                selectedIndex = pagerState.targetPage,
                selectedSize = 8.dp,
                unselectedSize = 6.dp
            )
        }
    }
}

I have tried centering the image in several places and none of them worked.

1

There are 1 best solutions below

1
Abdul Rahman On

It looks like the issue you're facing with the AutoSlidingCarousel might be due to the PagerState not being properly reset when it reaches the end, causing it to jump to the third page instead of looping back to the first. To fix this issue and center the images correctly, you can make the following modifications to your AutoSlidingCarousel composable:

@OptIn(ExperimentalFoundationApi::class)
@Composable
fun AutoSlidingCarousel(
    modifier: Modifier = Modifier,
    alignment: Alignment = Alignment.Center,
    autoSlideDuration: Long = AUTO_SLIDE_DURATION,
    itemsCount: Int,
    pagerState: PagerState = rememberPagerState(pageCount = itemsCount),
    itemContent: @Composable (index: Int) -> Unit
) {
    LaunchedEffect(pagerState.currentPage) {
        while (true) {
            delay(autoSlideDuration)
            pagerState.animateScrollToPage((pagerState.currentPage + 1) % itemsCount)
        }
    }

    Box(
        modifier = modifier.fillMaxSize(),
        contentAlignment = alignment
    ) {
        HorizontalPager(
            state = pagerState,
            modifier = Modifier.fillMaxSize()
        ) { page ->
            itemContent(page)
        }

        Surface(
            modifier = Modifier
                .padding(bottom = 8.dp)
                .align(Alignment.BottomCenter),
            shape = CircleShape,
            color = Color.Black.copy(alpha = 0.5f)
        ) {
            DotsIndicator(
                modifier = Modifier.padding(horizontal = 8.dp, vertical = 6.dp),
                totalDots = itemsCount,
                selectedIndex = pagerState.currentPage,
                selectedSize = 8.dp,
                unselectedSize = 6.dp
            )
        }
    }
}

I changed the pagerState initialization to use rememberPagerState instead of remember and provided the pageCount. This ensures that the pager state is properly initialized.

In the LaunchedEffect, I added a while (true) loop to continuously animate the scroll to the next page. This ensures that the carousel keeps looping through the images.

I removed the targetPage property when accessing the selectedIndex for the DotsIndicator. Now it directly uses pagerState.currentPage.