4

I've created a collapsible header in Compose with the NestedScrollConnection. Everything works perfectly but one addition had to be made: automatic scrolling to a certain item. The problem I have is that the header (connected using the NestedScrollConnection) does not update when triggering an animateScrollTo.

Found a similar version from the Android developer docs here (this is from the experimental Material3 library, but it also happens without):

val scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior()
Scaffold(
    modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
    topBar = {
        MediumTopAppBar(
            title = { Text("Medium TopAppBar") },
            navigationIcon = {
                Icon(imageVector = Icons.Filled.Menu, contentDescription = "Localized description")
            },
            scrollBehavior = scrollBehavior
        )
    },
    content = { innerPadding ->
        val listState = rememberLazyListState()

        val coroutines = rememberCoroutineScope()
        LaunchedEffect(key1 = Unit, block = {
            coroutines.launch {
                delay(5000)
                // Starts the scrollTo
                listState.animateScrollToItem(50, 0)
            }
        })

        LazyColumn(
            state = listState,
            contentPadding = innerPadding,
            verticalArrangement = Arrangement.spacedBy(8.dp)
        ) {
            val list = (0..75).map { it.toString() }
            items(count = list.size) {
                Text(
                    text = list[it],
                    modifier = Modifier.fillMaxWidth()
                )
            }
        }
    }
)

Even though scrolling to an item works and the item is visible the header did not update at all.

When looking to the documentation of the LazyListState animateScrollToItem it does not say anything about skipping nested scroll connections (like dispatchRawDelta does). Even with the linked example above the scrollTo item does not update the header state. The problem also occurs with a normal scrollable Column, LazyGrid etc.

I did think of other ways of fixing it:

  • Getting the amount of pixels scrolled and dispatch it to the nestedScrollConnection but there is no reliable way of getting the scrolled pixels from a LazyColumn
  • Measuring all items and passing that but when items would invalidate this will fail

I get the feeling that a part of this connection is missing. Does anyone have any ideas?

Marc
  • 1,094
  • 3
  • 17
  • 38
  • What is header supposed to look like? Is it possible to just remember some state e.g. `remember {mutableStateOf(header)}` which gets updated when animateToScrolll is called? – jns Dec 17 '22 at 17:50
  • @jns it should look like it has been scrolled (like collapsed). However that depends on the amount of pixels scrolled which is not passed to the listener (and it can't be retrieved either). – Marc Dec 19 '22 at 08:33
  • So `animateScrollToItem` is used not only to scroll to the top i.e. item == 0? What's the usecase here? – jns Dec 19 '22 at 13:47
  • `animateScrollToItem` is used to scroll to the given item index. It can be any index in the list. For example when animating to the 50th item the header should be collapsed as scrolling manually to the 50th item would also cause that. – Marc Dec 20 '22 at 16:25
  • 1
    @JacekKwiecień not yet. Reported it to Google: https://issuetracker.google.com/issues/262434128 – Marc Feb 02 '23 at 11:13

0 Answers0