Compose: 2 AppBars with different ScrollBehavior for single page

1k Views Asked by At

A "genius" designer wants a screen with 2 app-bars and different scroll behaviors. The top one should appear only when user scrolls till the begin of the screen, the second one should appear even when user scrolls back a little. I have attached a picture with illustration of 3 states I want to achieve using Jetpack-Compose.

States of the scroll

I wanted smth like following code (here I've used androidx.compose.material3):

val topAppBarState = rememberTopAppBarState()
val scrollOnlyInTopBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior(topAppBarState)
val scrollBehavior = TopAppBarDefaults.enterAlwaysScrollBehavior(topAppBarState)

Scaffold(
    modifier = Modifier
        .nestedScroll(scrollBehavior.nestedScrollConnection)
        .nestedScroll(scrollOnlyInTopBehavior.nestedScrollConnection),
    topBar = {
        Column {
            SearchBar(...)

            CenterAlignedTopAppBar(
                title = { Text(text = "Slide-out only in top") },
                scrollBehavior = scrollOnlyInTopBehavior,
            )
            CenterAlignedTopAppBar(
                title = { Text(text = "Slide-out event when scrolling back a little") },
                scrollBehavior = scrollBehavior,
            )
        }
    }
) {
    LazyVerticalGrid(columns = Fixed(2), ...)
}

But obviously it doesn't work because Modifier.nestedScroll of the Scaffold can have only one nestedScrollConnection. Please suggest me some workaround with Compose to implement this screen.

Update:

I was wrong, it's possible to correctly setup several `nestedScroll` modifiers for single compose container, here I just did it in wrong way.
1

There are 1 best solutions below

0
On

I just found mistake in the code above. I used single TopAppBarState for different Behavior-s, that's why they act similarly, and I wasn't able to achieve desired scroll effect. The effect reaches by using different TopAppBarState for each individual Behavior. Example below should work correctly:

val scrollOnlyInTopBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior(rememberTopAppBarState())
val scrollBehavior = TopAppBarDefaults.enterAlwaysScrollBehavior(rememberTopAppBarState())

Scaffold(
  modifier = Modifier
      .nestedScroll(scrollBehavior.nestedScrollConnection)
      .nestedScroll(scrollOnlyInTopBehavior.nestedScrollConnection),
  topBar = {
      Column {
          SearchBar(...)

          CenterAlignedTopAppBar(
              title = { Text(text = "Slide-out only in top") },
              scrollBehavior = scrollOnlyInTopBehavior,
          )
          CenterAlignedTopAppBar(
              title = { Text(text = "Slide-out event when scrolling back a little") },
              scrollBehavior = scrollBehavior,
          )
      }
  }
) {
      LazyVerticalGrid(columns = Fixed(2), ...)
}