Zoltan Demant
04/03/2025, 11:37 AMColumn {
Toolbar()
Box(Modifier.consumeWindowInsets(WindowInsets.statusBars)) {
Content()
}
}
Zoltan Demant
04/03/2025, 11:38 AMColumn {
Content(Modifier.consumeWindowInsets(WindowInsets.navigationBars)
NavBar()
}
Instead of having nested Scaffolds.Zoltan Demant
04/03/2025, 11:39 AMStylianos Gakis
04/03/2025, 12:47 PMStylianos Gakis
04/03/2025, 12:49 PMconsumeWindowInsets
modifier where needed.Zoltan Demant
04/03/2025, 1:06 PMStylianos Gakis
04/03/2025, 1:12 PMZoltan Demant
04/03/2025, 1:37 PMStylianos Gakis
04/03/2025, 1:39 PMZoltan Demant
04/03/2025, 1:41 PMZoltan Demant
04/03/2025, 1:44 PMColumn(modifier) {
toolbar?.invoke()
Box(Modifier.weight(1f)) {
content(None)
if (fab != null) {
Box(Modifier.align(BottomEnd).padding(KeylineSmall)) {
fab()
}
}
}
footer?.invoke()
}
Alex Vanyo
04/03/2025, 8:25 PMScaffold
in material3
while keeping the same API shape - the only difference in behavior with the non-subcomposition version is that the PaddingValues
passed to the content won’t be correct if you calculate the values of them directly in composition (but you probably should avoid doing that anyway)
I think it should be mostly copy-paste-able outside of androidx?Zoltan Demant
04/04/2025, 7:06 AMandroidx.benchmark:benchmark
? Id be curious to know the numbers, because just eyeballing I can already tell a few differences:
• Even with just one scaffold, animations between screens are a bit smoother; it certainly feels like the complexity of a screen was multiplied like O(N) before, and is just O(1) now. I dont think anyone would have complained about the earlier case, but Im sure people will feel the difference, which is amazing.
• With nested scaffolds, the difference is ridiculous. Jumping through ALL hoops I knew of compose earlier got it to like 95% smooth (contrary to like 30% before); now its 100% without me even thinking about recompositions, stability, and a trillion of the other things.
Any advice around the consumption of windowInsets for nested scaffolds? Now that it "doesnt matter" that I nest scaffolds, Id love to continue doing it (I love that it positions everything correctly, minus the inset issues ofc). I certainly dont want to overcomplicate things more than they already are, so heres the most minimal approach I could devise: Make composables like top/bottom nullable and depending on their existence, consume top/bottom, then figure out an elegant way to skip content padding in the outer scaffold.Zoltan Demant
04/04/2025, 2:09 PMtopBar != null
(they are not nullable in the androidx code).
Maybe Ill run into some edge case, but with this I can have one scaffold with just a toolbar+content, a nested one with content+fab, and sometimes switch to another with content+bottomBar, and all of the insets are correct!
@Composable
private fun rememberConsumedInsets(
insets: WindowInsets,
consumeTopInsets: Boolean,
consumeBottomInsets: Boolean,
consumeHorizontalInsets: Boolean,
density: Density = LocalDensity.current,
ld: LayoutDirection = LocalLayoutDirection.current,
) = remember(insets, consumeTopInsets, consumeBottomInsets, consumeHorizontalInsets, density, ld) {
WindowInsets(
left = if (consumeHorizontalInsets) insets.getLeft(density, ld) else 0,
right = if (consumeHorizontalInsets) insets.getRight(density, ld) else 0,
top = if (consumeTopInsets) insets.getTop(density) else 0,
bottom = if (consumeBottomInsets) insets.getBottom(density) else 0,
)
}
Alex Vanyo
04/04/2025, 4:23 PMrememberConsumedInsets
? Modifier.consumeWindowInsets(innerPadding)
, where the innerPadding
is the PaddingValues
that come from the Scaffold
should do what you need to manage consumption correctly (and that should still work even with the subcomposition-free Scaffold
)Zoltan Demant
04/05/2025, 9:12 AMZoltan Demant
04/07/2025, 8:55 AMwrapper: Boolean
to my Scaffold, which leads to it consuming insets like !wrapper || topBar != null
. So root scaffolds consume all insets, and if there is nesting then each scaffold consumes what it uses only (and inner-most scaffold consumes everything thats left).
If anyone knows a way I could automate that (remove wrapper: Boolean) then Id love to know. I dont think its the most intuitive way to do it, because the different screens are often not direct children of each other, so specifying that the root scaffold is a wrapper is knowing too much about what the other screens are doing. So basically what I want is a compositionLocal that flows from inside -> out.Stylianos Gakis
04/07/2025, 9:16 AMZoltan Demant
04/07/2025, 9:46 AMZoltan Demant
04/07/2025, 9:55 AMStylianos Gakis
04/07/2025, 11:22 AMAlex Vanyo
04/07/2025, 5:32 PMWindowInsets(0, 0, 0, 0)
to contentWindowInsets
for each of your `Scaffold`s? To avoid any of the contentPadding
accumulating any values from windowInsets
directly, unless there is a bar.Zoltan Demant
04/08/2025, 8:53 AM