Stylianos Gakis
11/20/2023, 10:35 AMTopAppBarDefaults.enterAlwaysScrollBehavior()
and it seems like it collapses the content, but always keeps the window insets part at the top.Stylianos Gakis
11/20/2023, 10:35 AMStylianos Gakis
11/20/2023, 10:38 AMStylianos Gakis
11/20/2023, 10:58 AM@Composable
internal fun chatTopAppBarWindowInsets(
windowInsets: WindowInsets,
topAppBarScrollBehavior: TopAppBarScrollBehavior,
): WindowInsets {
val density = LocalDensity.current
val layoutDirection = LocalLayoutDirection.current
var resultingInsets by remember { mutableStateOf(windowInsets) }
LaunchedEffect(topAppBarScrollBehavior.state, density, layoutDirection) {
snapshotFlow { topAppBarScrollBehavior.state.collapsedFraction }.collectLatest { fraction ->
resultingInsets = windowInsets.times(fraction, density, layoutDirection)
}
}
return resultingInsets
}
private fun WindowInsets.times(times: Float, density: Density, layoutDirection: LayoutDirection): WindowInsets {
val multiplyBy = 1 - times
return WindowInsets(
left = (getLeft(density, layoutDirection) * multiplyBy).roundToInt(),
right = (getRight(density, layoutDirection) * multiplyBy).roundToInt(),
top = (getTop(density) * multiplyBy).roundToInt(),
bottom = (getBottom(density) * multiplyBy).roundToInt(),
)
}
Using topAppBarScrollBehavior.state.collapsedFraction
basically and it does seem to work, while being like super quick about it, but that’s fine 😄
On the call-site I do this
TopAppBarWithBack(
scrollBehavior = topAppBarScrollBehavior,
windowInsets = chatTopAppBarWindowInsets(TopAppBarDefaults.windowInsets, topAppBarScrollBehavior),
...
Will just use this for now until(if) something better pops up 😄Stylianos Gakis
11/20/2023, 10:59 AMZoltan Demant
11/20/2023, 1:15 PMStylianos Gakis
11/20/2023, 1:16 PMZoltan Demant
11/20/2023, 1:18 PMStylianos Gakis
11/20/2023, 1:19 PMascii
11/20/2023, 2:05 PMwindowInsets = WindowInsets.systemBars.only(WindowInsetsSides.Horizontal)
which lets content scroll behind the status bar, because nothing's consuming it. But that screws up AppBar, because it will of course draw under the status bar now.
I'd like a way to leave space for the status bar, then draw the AppBar, but also let AppBar collapse into the status bar. @Zoltan Demant perhaps you are doing something special. It doesn't work for:
Column {
TopAppBar(windowInsets = horizontal)
Content()
}
ascii
11/20/2023, 2:07 PMStylianos Gakis
11/20/2023, 2:07 PMColumn {
val density = LocalDensity.current
var topAppBarHeight by remember { mutableStateOf(0.dp) }
TopAppBar(
onNavigateUp = onNavigateUp,
topAppBarScrollBehavior = topAppBarScrollBehavior,
onSizeChanged = { with(density) { topAppBarHeight = it.height.toDp() } },
)
Box(
modifier = Modifier
.consumeWindowInsets(PaddingValues(top = topAppBarHeight)),
So now in your content, just use the insets as you wish, because if the top app bar is consumed then you know that it’s not gonna double apply it, if it’s not present then you will have them available to youascii
11/20/2023, 2:09 PMStylianos Gakis
11/20/2023, 2:10 PMZoltan Demant
11/20/2023, 2:13 PMStylianos Gakis
11/20/2023, 2:14 PMonSizeChanged
and then it applies the right consumed insets number. Might be 1 frame late sometimes, but so would Subcomposition if I understand that correctly 😄ascii
11/20/2023, 2:33 PMScaffold(
topBar = { TopAppBar(scrollBehavior = enterAlways) },
) { innerPadding ->
// ^ on topBar expand/collapse, innerPadding changes, causes Content to recompose
// Bad!
Content(innerPadding)
}
An identical layout without the unnecessary recomposition would be:
Column {
TopAppBar(scrollBehavior = enterAlways) // <- expand/collapse still works
Content() // <-- does not cause Content to recompose the entire time topBar does its thing
// Good!
}
In other words, TopAppBar changes are contained to itself, as it should be. Why should sibling composables care about each other? It was a night and day difference for us when we tested between them, some alphas earlier. Not sure if anything's changed with Scaffold itself, or with Compose (we didn't have experimentalStrongSkipping
for example), but I guess we'll revisit it later. We'd really like proper edge-to-edge as it looks nice.Zoltan Demant
11/20/2023, 2:48 PMAlbert Chang
11/20/2023, 3:59 PMStylianos Gakis
11/20/2023, 4:22 PMascii
11/21/2023, 2:25 AM