https://kotlinlang.org logo
#compose
Title
# compose
f

Francisco Vital Serrão Pereira De Carvalho

03/06/2023, 11:18 AM
Hey guys! We are currently working with the horizontal pager from the accompanist library. In our use-case we are using 3 tabs, all of them with only a text. We notice this bug when clicked the center of the middle tab the click is not registered, we also tried with more than 3 tabs but observed this same behavior every time we had an odd number of tabs, always in the middle one. (If clicked outside this center everything works as expected). TabRow and Tab are both from Material3. I will post some code in the thread, thanks!
2
Versions:
accompanist = "0.29.1-alpha"
androidxComposeMaterial3 = "1.1.0-alpha07"
Copy code
TabRow(
                        selectedTabIndex = pagerState.currentPage
                    ) {
                        pages.forEachIndexed { index, name ->
                            Tab(
                                modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
                                selected = pagerState.currentPage == index,
                                onClick = {
                                    coroutineScopePager.launch {
                                        pagerState.scrollToPage(index)
                                    }
                                },
                                text = {
                                    Text(
                                        text = stringResource(id = name),
                                        color = MaterialTheme.colorScheme.primary
                                    )
                                },
                                unselectedContentColor = MaterialTheme.colorScheme.onSurfaceVariant,
                            )
                        }
                    }
r

Rebecca Franks

03/06/2023, 11:32 AM
Have you tried using the androidx pager? We will soon be deprecating the accompanist version. I wonder if androidx pager is seeing the same issue 🙂 https://github.com/google/accompanist/pull/1504
g

Guilherme Delgado

03/06/2023, 11:42 AM
It’s an odd behaviour. The Tab and TabRow are from
material3
, can the `accompanist pager`/`androidx pager` influence their click behaviour? 🤔
But nice to know it will be deprecated 😊
r

Rebecca Franks

03/06/2023, 11:43 AM
Is it that its not scrolling to the page? or that the click event is not firing?
g

Guilherme Delgado

03/06/2023, 11:43 AM
click not firing
it’s like the tab’s touch area getting wrongly calculated (instead of using the tab maxsize)
@Rebecca Franks hope it helps, as you can see, when we click on the “center tab’s text” there’s no click response
r

Rebecca Franks

03/06/2023, 12:03 PM
Whats the reason for adding the nested scroll connection on the tab item?
g

Guilherme Delgado

03/06/2023, 12:06 PM
nice catch 🤔 @Francisco Vital Serrão Pereira De Carvalho can you check this please? I did it 😉
r

Rebecca Franks

03/06/2023, 12:08 PM
FWIW, tried similar with accompanist and pager, both are working without that scroll connection, wondering if that is somehow interfering with clicks.. Seems a bit strange that behaviour though
g

Guilherme Delgado

03/06/2023, 12:15 PM
I’ve commented the modifier but the same happens.
I believe it was a copy paste error from this logic:
Copy code
Scaffold(
    modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
Copy code
Scaffold
 -- Column
       -- TabRow
            -- Tabs
       -- HorizontalPager
r

Rebecca Franks

03/06/2023, 12:21 PM
can you share the full composable?
g

Guilherme Delgado

03/06/2023, 12:26 PM
Copy code
val listState = rememberLazyListState()
val scrollState = rememberScrollState(listState, lastItemOffset)
val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState())

Scaffold(
    modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
    topBar = {
        when (pagerState.currentPage) {
            0 -> TopBarA
            1 -> TopBarB
            2 -> TopBarC
        }
    }
) {
    Column(
        Modifier
            .fillMaxSize()
            .padding(it)
    ) {
        TabRowTheme {
            TabRow(selectedTabIndex = pagerState.currentPage) {
                pages.forEachIndexed { index, name ->
                    Tab(
                        selected = pagerState.currentPage == index,
                        onClick = {
                            coroutineScopePager.launch {
                                pagerState.scrollToPage(index)
                            }
                        },
                        text = {
                            Text(
                                text = stringResource(id = name),
                                color = MaterialTheme.colorScheme.primary
                            )
                        },
                        unselectedContentColor = MaterialTheme.colorScheme.onSurfaceVariant,
                    )
                }
            }
        }
        HorizontalPager(
            modifier = Modifier.fillMaxSize(),
            count = pages.size,
            state = pagerState,
            userScrollEnabled = false,
        ) { page ->
            when (page) {
                ...
            }
        }
    }
}
Another sample, with the touch box messed up
this sample is even stranger, it seems only the word “Notes” don’t react to touch
r

Rebecca Franks

03/06/2023, 12:30 PM
Have you got another composable overlaying that section of the screen perhaps?
g

Guilherme Delgado

03/06/2023, 12:31 PM
could it be the pull to refresh? 🤔
r

Rebecca Franks

03/06/2023, 12:31 PM
Maybe?
g

Guilherme Delgado

03/06/2023, 12:31 PM
Well… that’s the area but, the pull to refresh is a child from the pager items
could it be the z index messing it up?
(we didn’t change the z index)
Ok, so yeah it’s the pull to refresh:
Screen Recording 2023-03-06 at 12.34.50.mov
how can we fix it now? 😅
r

Rebecca Franks

03/06/2023, 12:36 PM
Oh dear 🙈 Is it in the page or the whole composable?
g

Guilherme Delgado

03/06/2023, 12:36 PM
in the pager items
Copy code
private fun Item(
    ....
    pullRefreshStateTasks: PullRefreshState,
) {
    Box(Modifier.pullRefresh(pullRefreshStateTasks)) {
        LazyColumn(...){ ... }                     
        PullRefreshIndicator(
            modifier = Modifier.align(Alignment.TopCenter),
            state = pullRefreshStateTasks,
            contentColor = MaterialTheme.colorScheme.primary,
            refreshing = false
        )
    }
each
HorizontalPager
item has it’s own pull to refresh that will fire a different action on the VM (state hoisting). But if needed we could move that logic to the HorizontalPager “level”, and react to the page selected… (in an UX perspective it will be the same, you cannot change the page while loading)
r

Rebecca Franks

03/06/2023, 12:43 PM
Can you file a bug for this in the meantime? I don't think the pull refresh component should be interfering with clicks when its not visible.
g

Guilherme Delgado

03/06/2023, 12:43 PM
yeah sure
google issue tracker or github? (can you provide link please 🙂 )
so as a quick fix, this works:
Copy code
TabRow(
    modifier = Modifier.zIndex(Float.MAX_VALUE),
i’ll file a bug
Thanks!
g

Guilherme Delgado

03/06/2023, 1:01 PM
l

Louis Pullen-Freilich [G]

03/06/2023, 6:02 PM
Could you share some more of the code / reproduction steps? Does it only happen if you try and press a tab while the pull refresh is currently active?
r

Rebecca Franks

03/06/2023, 6:04 PM
I reproduced it with just adding the pull to refresh component inside a pager item, without activating the pull to refresh you can't click on the middle item area, i guess its regardless of what you put there.
l

Louis Pullen-Freilich [G]

03/06/2023, 6:04 PM
Only the middle item though? 😕
If you have that as a sample project you could add to the bug that would be helpful anyway
r

Rebecca Franks

03/06/2023, 6:05 PM
yup, that little section where the pull to refresh would appear.
sure - will attach one to the bug too.
l

Louis Pullen-Freilich [G]

03/06/2023, 6:07 PM
Ahh, ok, thanks. If you remove the `Modifier.pullRefresh`but keep the indicator, does it still have the same problem?
r

Rebecca Franks

03/06/2023, 6:09 PM
Yup, I believe its the indicator
🥳
272 Views