```entry<About>( metadata = BottomSheetSceneSt...
# compose
u
Copy code
entry<About>(
    metadata = BottomSheetSceneStrategy.bottomSheet()
) {
    AboutScreen(
        onClose = { backStack.removeLastOrNull() }
    )
}
When using
BottomSheetStrategy
in
Nav3
When I have such sheet-y screen displayed and press system back button, it slides away nicely. But when I do
backstack.removeLastOrNull()
from a button inside the sheet (X button on toolbar) it hides instantly Why? Looking at
onBack
default value it does the same so wth? How do I make it behave the same?
w
This is just how bottom sheets work in Compose, if you remove it from composition it disappears instantly. The trick with a regular ModalBottomSheet is to launch a state hide, listen for the completion, and then remove the composable. You might need a similar trick here, where the back button click hides the sheet and only calls into
removeLastOrNull()
when the animation finishes.
u
But OS back click works fine and that is just removeLastOrNull as well
which is what I dont understand how come that works
w
The bottom sheet listens for the back press and does what I described above.
u
but then than means its still on bacstack and just invisible?
w
Yes, until the animation finishes. You should be able to log that to confirm.
Or well, it's not invisible. It's still visible, just animating.
u
no even after it finishes, im speculating though
nevrrmind doesnt make sense os back triggers navdisplay.onBack, which just backstack.removeOrNull how can it inject it self here for it to animate and only then pop? seems like a parent (navdisplay) job
can child somehow object?
w
Presumably a
BackHandler
, but on Android it might just be catching the dialog window finish?
u
you mean backhandler private to the sheet?
if so.. then sure it can play bottomSheetState.hide(), but then that means its still in composition just hidden
nevermind I'll check but it's odd
w
Right, it has to remain in composition to play the animation. But once the animation is done, it just calls
onDismiss
which flows to your defined
onBack
which pops the back stack.
u
okay so it does have a reference to navdisplay.onback? okay then it makes sense thanks!
guess I have to somehow do the same
how will i allow a screen composable to get a reference to the state? i mean screen composables are oblivious theyre a bottom sheet
w
I don't know if it'd work, but you can use NavEvent to propagate your own back press. Which should flow through all of the infra and might notify the bottom sheet as if it was sent system back.
This mechanism wouldn't care what wraps the destination, it just propagates a back nav event.
u
or get the ref to onBack somehow to the screen... maybe composition local?
I mean something that a screen can call that would trigget the hide()+onBack probsbly on the decoration lecel
i
Navigation3 1.1.0-alpha04 introduced the ability for overlay scenes to stay in composition until their own exit animation is finished: https://developer.android.com/jetpack/androidx/releases/navigation3#1.1.0-alpha04
😮 1
No custom back logic needed, just reading the release notes 🙂
w
It looks like the Nav3 sample isn't updated yet. I landed on https://developer.android.com/guide/navigation/navigation-3/recipes/bottomsheet
u
wdym? I can open Ian's link fine funny enough I'm on alpha 05, but yea it's not referenced in the recipes repo so I missed it
w
Sorry, I meant from searching.
i
Yep, recipes are going to lag behind the actual releases - generally that 'catch up' phase is as each release goes through beta/RC/stable
u
thank you since you're here, boss, could you maybe please poke at this one? couple of days ago we were discussing this https://avatsav.dev/hello-retain/, usage of
retain
api in nav3, which currently doesn't really work with nav3 due to, or rather this PR fixes it https://android-review.googlesource.com/c/platform/frameworks/support/+/3904490 which seems like completed but CICD failed, so not merged .. looks like a flake and then forgoten?
i
You'll want to copy/paste the decorator into your own project - that API won't be part of Nav3 1.1
u
Is it coming later or not at all?
i
I think we're looking at making it a recipe first
u
recipes are meant as
nav3x
incubation space?
i
I think the general pattern you'll see is something is introduced as a recipe first, we iterate on the design there, then it 'graduates' into the library itself
u
gotcha, thanks
about that bottom sheet sample .. it does seem to work, but my sheet is blue fyi 😄
Copy code
ModalBottomSheet(
    onDismissRequest = onBack,
    containerColor = Color.Blue, <-----
    sheetState = sheetState,
    modifier = Modifier.heightIn(min = minHeight.dp),
) {
    entry.Content()
}
i
Good thing you copied it over and can change it to be whatever you want or make that a parameter on your
bottomSheet
metadata, phew
u
I'm just reporting back 😄 cmon thank you
i
we use a lot more bright colors in our tests because they make screenshot testing and slow motion videos a lot easier to parse
u
makes sense
if I may, I'm looking at the source
Copy code
return object : OverlayScene<Any> {
    override val key = entry.contentKey
    override val entries = listOf(entry)
    override val previousEntries = entries.dropLast(1)
    override val overlaidEntries = previousEntries.takeLast(1)

    lateinit var sheetState: SheetState <-------

    override val content: @Composable (() -> Unit) = {
        sheetState = rememberModalBottomSheetState()
        val minHeight = LocalWindowInfo.current.containerSize.height * 0.2 // 50% height
        ModalBottomSheet(
            onDismissRequest = onBack,
            sheetState = sheetState,
            modifier = Modifier.heightIn(min = minHeight.dp),
        ) {
            entry.Content() <---------
        }
    }
I'm not sure how you managed it, but say you didn't come to save the day, but I'd have to make it work manually in the beginning we discussed the entry (content) composable somehow having access to this
sheetState
from the stragegy/ anything from decoration really and I was wondering what's the idiomatic way of doing this? composition local? i.e. for entry composable to query some`LocalSheetState.get()` (`provides`ed by the
content
in strategy) and call
hide
on it? or this this direction of communication not desired at all?
i
The reason that we added this new API in the first place was because there was no good way to do this kind of thing at all
u
maybe I'll generalize, say I have a
NavEntryDecorator
that access a DI graph and want's to provide it to the entry or any parameter to the entry composable but since
entry.Content()
si final I'm not sure how - other than composition local
i
yes, a composition local is the best way to send information down the composition subtree
u
thanks!