2

I am working on a an android jetpack compose screen. Simply, the page has a TabRow with 3 tabs. Every tab has LazyColumn which shows some ui components in a scrollable manner. Also, there is one HorizontalPager, which contains these LazyColumns, for the user to swipe between tabs nicely.

Here is the code;

@Composable
fun StatsContent(viewModel: StatsViewModel) {
    val state = viewModel.soloGameStatsState.collectAsStateWithLifecycle()
    LaunchedEffect(LocalContext.current) {
        viewModel.getSoloStats()
    }

    val titles = listOf("Tab 1", "Tab 2", "Tab 3")
    val pagerState = rememberPagerState { titles.size }
    var tabIndex = pagerState.currentPage
    val coroutineScope = rememberCoroutineScope()

    Scaffold(
        topBar = {
            TabRow(selectedTabIndex = tabIndex) {
                titles.forEachIndexed { index, title ->
                    Tab(
                        text = { Text(title) },
                        selected = tabIndex == index,
                        onClick = { tabIndex = index
                            coroutineScope.launch {
                                pagerState.animateScrollToPage(index)
                            }
                        }
                    )
                }
            }
        },
        content = { paddingValues ->
                HorizontalPager(
                    state = pagerState,
                    pageSpacing = 16.dp
                ) {
                    Column(
                        modifier = Modifier
                            .padding(paddingValues)
                            .fillMaxSize(),
                        verticalArrangement = Arrangement.Center,
                        horizontalAlignment = Alignment.CenterHorizontally
                    ) {
                        if (tabIndex == 1 || tabIndex == 0) {
                            RenderStatsOne(state.value)
                        } else if (tabIndex == 2) {
                            RenderStatsTwo(stats = state.value)
                        }
                    }
                }

        }
    )
}
@Composable
fun RenderStatsOne(stats: Stats?) {
    if (stats != null) {
        LazyColumn(
            modifier = Modifier
                .fillMaxSize()
                .paint(
                    painterResource(id = R.drawable.bg_results),
                    contentScale = ContentScale.Crop
                )
        ) {
            item { ...

@Composable
fun RenderStatsTwo(stats: Stats?) {
    if (stats != null) {
        LazyColumn(
            modifier = Modifier
                .fillMaxSize()
                .paint(
                    painterResource(id = R.drawable.bg_results),
                    contentScale = ContentScale.Crop
                )
        ) {
            item { ...

Here is the issue; Once a page change occurred, it does not matter user triggered it with a tab click or did left-right swipe on the pager, the LazyColumn inside the new visible page is becomes scrollable with a significant delay. Therefore, when I change the page and then quickly try to swipe up and down, the HorizontalPager gets this gesture and a page change is performed.

I see that pagerState has a field called isScrollInProgress. This becomes true as the scroll started. LazyColumn gets focus and becomes scrollable, only when this field becomes false. Unfortunately, this becomes false with a significant delay after the page change is completed.

I am looking for a solution which will make the LazyColumn scrollable as soon as the the new page content it fullu visible.

Any help? Thanks a lot in advance.

1 Answer 1

1

Not sure why this happens, but the issue seems to be related with the spring animation that animateScrollToPage function uses by default. You can reduce the delay by changing the stiffness of the spring animation (the default being used is StiffnessMediumLow):

pagerState.animateScrollToPage(index, animationSpec = spring(stiffness = Spring.StiffnessMedium))

But this doesn't really solve it, it still happens but with a smaller delay. I was able to solve it using the tween animation instead:

pagerState.animateScrollToPage(index, animationSpec = tween(durationMillis = 200))

In this case, as soon as the animation ends the LazyColumn becomes scrollable, and the components inside it, become clickable.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.