Jetpack Compose LazyColumn items scroll over stickyHeader and does not scroll to last item
Asked Answered
U

5

18

I am struggling with the jetpack compose LazyColumn and the stickyHeader functionality. Basically the static view works well, but once I start scrolling, the items would go over the sticky headers, the scrolling starts a weird behaviour and the last item would never be visible as the scrolling always bounces back.

Here's how it looks like:

enter image description here

Here's the composable:

@OptIn(ExperimentalFoundationApi::class)
@Composable
fun CollectionsScreen(
    collectionsLive: LiveData<List<CollectionsView>>,
    onCollectionChanged: (ICalCollection) -> Unit
    /* some more hoisted functions left out for simplicity */
) {

    val list by collectionsLive.observeAsState(emptyList())
    val grouped = list.groupBy { it.accountName ?: it.accountType ?: "Account" }

    LazyColumn(
        modifier = Modifier.padding(8.dp)
    ) {

        item {
            Text(
                stringResource(id = R.string.collections_info),
                textAlign = TextAlign.Center,
                modifier = Modifier.padding(bottom = 16.dp)
            )
        }

        grouped.forEach { (account, collectionsInAccount) ->
            stickyHeader {
                Text(
                    account,
                    style = MaterialTheme.typography.titleLarge,
                    fontWeight = FontWeight.Bold,
                    modifier = Modifier.padding(
                        top = 16.dp,
                        start = 8.dp,
                        end = 16.dp,
                        bottom = 8.dp
                    )
                )
            }

            items(
                items = collectionsInAccount,
                key = { collection -> collection.collectionId }
            ) { collection ->

                CollectionCard(
                    collection = collection,
                    allCollections = list,
                    onCollectionChanged = onCollectionChanged,
                    /* some more hoisted functions left out for simplicity */
                    modifier = Modifier
                        .fillMaxWidth()
                        .padding(bottom = 8.dp)
                        .animateItemPlacement()
                        .combinedClickable(
                            //onClick = { onCollectionClicked(collection) }
                         )
                )
            }
        }
    }
}

I am really not sure what is causing this issue as the code itself is pretty straightforward from the example provided in the documentation. Only the CollectionCard itself is a more complex structure. I have also tried removing the header text (the first item) and removed the Modifier.animateItemPlacement() for the card, but with no difference, the problem stays the same... The composable itself is used in a Compose View within a Fragment, but there is no nested scrolling. Do you have any idea what could cause this strange behaviour? Or might this be a bug when using cards within the LazyColumn with sticky headers?

UPDATE: It seems like the problem nothing to do with the stickyHeader, but somehow with the LazyColumn. If I replace the "stickyHeader" just with "item", the problem still persists... Only when I replace the lazyColumn with a column it would work. But I assume that there must be a solution for this problem...

Ultimatum answered 13/6, 2022 at 13:49 Comment(5)
I am not sure but may be due that for loop your compose function recomposing which is very bad for performanceBelloir
Well, loops should actually not be an issue in compose... The code follows the provided example from the documentation: developer.android.com/jetpack/compose/lists#sticky-headersUltimatum
I have the exact same issue, did you figure out any solution for this?Outgeneral
Add background color to that sticky headerSantasantacruz
I'd suggest creating an issue on the issuetracker in addition to whatever approach you decide to use. stickyHeader without a default background just seems wrong. Last time I checked there was no issue for it yet.Quark
Q
15

In general, if you are using Material or Material3 theming, you can wrap your stickyHeader content in a Surface to automatically make it non-transparent with your theme's standard (or customized) coloring scheme. Surface lets you raise the stickyHeader above your table's other contents.

stickyHeader {
    Surface(Modifier.fillParentMaxWidth()) {
        Text("Header")
    }
}

You can customize the Surface at your heart's desire.

I'd create another issue for the bounciness problem, it looks like a separate concern.

Quark answered 3/2, 2023 at 10:40 Comment(2)
This seems to solve the issue.Britteny
I agree. Have a cookie.Donets
A
2

Setting the stickyHeader background color will help.

stickyHeader {
                Text(
                    "text",
                    modifier = Modifier.padding(
                        top = 16.dp,
                        start = 8.dp,
                        end = 16.dp,
                        bottom = 8.dp
                    )
                   .background(colorResource(id = R.color.white))
                )
            }
Argali answered 11/7, 2022 at 7:22 Comment(2)
Doesn't solve the problem with the items going over the sticky headerSynchronize
@AndroidDev This answer worked for me in 1.3.0-rc01.Meghanmeghann
G
0

I don't know if you solved it yet, but try to fillMaxWidth and set the background. This code worked for me.

Text(
          account,
          style = MaterialTheme.typography.titleLarge,
          fontWeight = FontWeight.Bold,
          modifier = Modifier
              .padding(
                       top = 16.dp,
                       start = 8.dp,
                       end = 16.dp,
                       bottom = 8.dp
                      )
              .fillMaxWidth()
              .background(MaterialTheme.colors.background)
    )
Globin answered 28/9, 2022 at 18:2 Comment(0)
Z
-1

Just provide a background for the sticky header.

Zymase answered 30/1, 2023 at 12:7 Comment(1)
Instead of simply providing the answer directly, try writing a detailed comment that explains the solution, as long as the explanation is not too lengthy. @Prashant Singh.Predict
T
-2

You just could replace stickyHeader{} for item{}, you will have the expected result

Teofilateosinte answered 26/4, 2023 at 9:48 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.