Search code examples
androidkotlinandroid-jetpack-composejetpack-compose-accompanist

Accompanist HorizontalViewPager delay in transition when swiping


I am using HorizontalViewPager from the Accompanist library, and one thing I've noticed is a delay in page transitions when swiping.

For some reason the page only really changes the text when you have swiped more than halfway through the next page. If you swipe less than halfway through the next page the text reverts back to its previous state. What I want is that the user immediately sees the right text state, I don't want the user to have to swipe more than halfway to see the changes.

Composable:

@Composable
fun TutorialPage(page: TutorialPage) {
    Column {
        Spacer(
            modifier = Modifier.height(16.dp)
        )

        Column(
            modifier = Modifier
                .weight(1f)
                .fillMaxSize(),
            horizontalAlignment = Alignment.CenterHorizontally,
        ) {

        }

        Spacer(
            modifier = Modifier.height(16.dp)
        )

        Column(
            horizontalAlignment = Alignment.CenterHorizontally,
            verticalArrangement = Arrangement.Bottom,
        ) {
            Column(
                modifier = Modifier
                    .padding(start = 32.dp, end = 32.dp)
            ) {
                Text(
                    page.title,
                    style = MaterialTheme.typography.displayMedium,
                    textAlign = TextAlign.Center,
                    fontFamily = FontFamily(
                        Font(R.font.manrope_medium)
                    )
                )

                Spacer(
                    modifier = Modifier.height(8.dp)
                )

                Text(
                    page.description,
                    style = MaterialTheme.typography.titleMedium,
                    textAlign = TextAlign.Center,
                    fontFamily = FontFamily(
                        Font(R.font.manrope_medium)
                    ),
                    modifier = Modifier.alpha(0.7f)
                )
            }

            Spacer(
                modifier = Modifier.height(32.dp)
            )

            Row(
                modifier = Modifier.padding(16.dp)
            ) {

            }
        }
    }
}
@OptIn(ExperimentalPagerApi::class)
@Composable
fun TutorialScreen(
    viewModel: TutorialScreenViewModel,
    state: TutorialScreenState
) {
    val pagerState = rememberPagerState()

    Column {
        Column(
            modifier = Modifier.weight(1f)
        ) {
            HorizontalPager(
                count = state.tutorial.pages.size,
                state = pagerState
            ) {
                TutorialPage(state.tutorial.pages[pagerState.currentPage])
            }
        }

        Row(
            modifier = Modifier
                .padding(16.dp)
                .fillMaxWidth(),
            horizontalArrangement = Arrangement.Center
        ) {
            repeat(state.tutorial.pages.size) {
                Box(
                    modifier = Modifier
                        .clip(CircleShape)
                        .size(10.dp)
                        .background(if (it == pagerState.currentPage) Color.Gray else Color.LightGray)
                ) {

                }
                Spacer(
                    modifier = Modifier.width(8.dp)
                )
            }
        }
    }
}

View model:

@HiltViewModel
class TutorialScreenViewModel @Inject constructor() : ViewModel() {

    private val _state = mutableStateOf(
        TutorialScreenState(tutorial)
    )

    val state: State<TutorialScreenState>
        get() = _state

    private val tutorial: Tutorial
        get() =
            Tutorial.Builder()
                .addPage(
                    TutorialPage(
                        title = "Creating a project",
                        description = "Creating a project is easy! To do so, simply tap the squircle-shaped plus button at the bottom right of your home screen.",
                        image = R.drawable.tutorial_img_1
                    )
                )
                .addPage(
                    TutorialPage(
                        title = "Setting up a project",
                        description = "From then, you will see a screen in which you can input your project's name, width, and height. Confused where to start? Feel free to use some of PixaPencil's ready made quick presets or add your own for future use.",
                        image = R.drawable.tutorial_img_2
                    )
                )
                .addPage(
                    TutorialPage(
                        title = "Let's draw",
                        description = "Now, you should be navigated to your drawing screen. The screen is divided into three main sections: your current color palette, your drawing view, and your tabs.",
                        image = 0
                    )
                )
                .addPage(
                    TutorialPage(
                        title = "Tools",
                        description = "PixaPencil has a wide variety of tools to get you started, such as: pencil tool, line tool, paint bucket tool, rectangle tool, square tool, ellipse tool, circle tool, and more.",
                        image = 0
                    )
                )
                .addPage(
                    TutorialPage(
                        title = "Features",
                        description = "As well as tools, PixaPencil has a wide variety of features get you started, such as: color palette functionality, replace color, import Lospec palette, pixel perfect mode, canvas filters, brushes, and more.",
                        image = 0
                    )
                )
                .addPage(
                    TutorialPage(
                        title = "Free and open source",
                        description = "PixaPencil is 100% free (as in freedom) and open source, the code is available on GitHub for anyone to view, download, or extend. We are always open for contributors to the project.",
                        image = 0
                    )
                )
                .addPage(
                    TutorialPage(
                        title = "Join the community",
                        description = "PixaPencil has a vibrant community on Discord, which you can join here.",
                        image = 0
                    )
                )
                .build()
}

Tutorial:

class Tutorial private constructor(val pages: MutableList<TutorialPage>) {

    class Builder {
        private val pages: MutableList<TutorialPage> = mutableListOf()

        fun addPage(page: TutorialPage): Builder {
            pages.add(page)
            return this
        }

        fun build(): Tutorial {
            return Tutorial(pages)
        }
    }
}

Page:

data class TutorialPage(
    val title: String,
    val description: String,
)

I've tried to look online (the documentation) to find solutions, and I didn't find any nor did I find someone with the same problem with the Accompanist library.


Solution

  • Rather than using TutorialPage(state.tutorial.pages[pagerState.currentPage]) use TutorialPage(state.tutorial.pages[it]) where "it" is the builder index that pager gives you in lambda. Hope it helps :d