Reputation: 406
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.
Upvotes: 2
Views: 480
Reputation: 56
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.
Upvotes: 1