I’m trying to have a dynamic modal bottom sheet, b...
# compose
o
I’m trying to have a dynamic modal bottom sheet, based on the user selected
Copy code
var selectedUser: String? by remember {
   mutableStateOf(null)
}

ModalBottomSheetLayout(
    sheetState = sheetState,
    sheetContent = {
        selectedUser?.let {
            UserDetail(
                id = selectedUser, 
                onCloseClick = {
                    coroutineScope.launch {
                        sheetState.hide()
                        selectedUser = null
                    }
                }
            )
        } ?: Box(modifier = Modifier.fillMaxSize())
    },
) { 
... 
    coroutineScope.launch {
        selectedUser = "userid"
        sheetState.show()
    }
}
I added the default
Box
because otherwise there is an exception
java.lang.IllegalArgumentException: The initial value must have an associated anchor.
so my questions is do you guys think this is the right way of making a dynamic modal bottom sheet or is there a better way without going through the Box? (I know I could use scaffold but I don’t want interaction with the main screen)
h
I search a way to avoid this exception but I didn't manage to. Even the Accompanist Navigation Material (that you can use to navigate to a bottom sheet instead of showing it, but there are some others issues...) uses an empty content. This is a known issue.
Copy code
@Composable
private fun EmptySheet() {
    // The swipeable modifier has a bug where it doesn't support having something with
    // height = 0
    // b/178529942
    // If there are no destinations on the back stack, we need to add something to work
    // around this
    Box(Modifier.height(1.dp))
}
o
ah glad it’s a known issue! thanks for the response!
j
It's on our radar:) star the ModalBottomSheetLayout-related issue from the link above for updates
m
The struggle with bottom sheets is real. I wish it didn't require the scaffold to wrap the entire page. It makes it difficult for smaller re-usable components to show bottom sheets without the larger page knowing what's going to be in there.
j
Which component are we talking about here?
m
The best i've been able to do is to mimic the approach of snackbar and have a well known state that contains some data structure, and have the state have a show/hide capability.
@jossiwolf ModalBottomSheetScaffold and BottomSheetScaffold. I had a UX requirement to do an autocomplete type text using a bottom sheet when the user clicked into the text field. It required me to create my own wrapper for BottomSheetScaffold along with a custom state object. The implementation mimics how snackbars work with the ScaffoldState.
It works, but the lower levels of the page which trigger the autocomplete have to rely on the full page to have that scaffold in place.
j
We've heard feedback from developers around ModalBottomSheetLayout's API shape and are exploring a different design that doesn't require a host further up in your hierarchy. No promises but we're hoping to address it in M3 :) BottomSheetScaffold is a non-modal component though and more like a canonical layout, so it's API shape seems to make sense to us. Do you have more details on feedback around that?
m
I definitely understand the dilemma here, and why the decision was made the way it's made. However, i feel like a "BottomSheet" should always come up from the bottom of the root layout (regardless of modality), much like how Dialog is always centered in the root layout. I suspect there are a lot of technical hurdles though to make something like that happen in the non modal case. As far as snackbar goes, one of my main concerns about the snackbar is that it's coded in a way that makes using your own snackbar data definition impossible from what i can tell. You can provide your own layout through the host object, but you are stuck with the exact data form in SnackbarDataImpl. Mostly because SnackbarHostState.currentSnackbarData cannot be set from outside code.
h
I think it would be nice to handle bottom sheet with navigation (like Accompanist lib tries to do, but with less issue and more control). To me the main problem with current implementation of
ModalBottomSheetLayout
(even if we remove the "empty sheet bug") is to have one
ModalBottomSheetLayout
for multiple
sheetContent
. It makes things a little bit complicated to isolate composable correctly.
j
By definition, only modals will overlay. My understanding is we limit the
snackbarHost
to
SnackbarHostState
to be able to offer a default Material snackbar implementation. Fwiw
SnackbarData
is an interface, so that should allow your own definition if needed. Agree that it could be nicer though. File an issue? 🙂
I think it would be nice to handle bottom sheet with navigation
Do you have more details? What are you looking for beyond Accompanist (which will be upstreamed eventually🙂)?
h
I think Accompanist navigation-material is a nice API. I like the way we declare bottom sheet independently as we make for composable in a nav graph. It allows use to easily re-use a bottom sheet if needed and centralized behavior too. We do not use this currently in our apps because there are some small UI / behavior issues mainly related to the "no empty content bug". For example, animations are not working correctly when navigating backward/forward for example (by debugging in AS, I saw it was related to the "no empty content bug" (i.e content is moving to
EmptySheet
before
sheetState.hide()
call, causing a blink instead of a swipe down animation). It is a small issue but not really good for the user experience. Also, it seems that it is not recommended / not possible to override some behavior (but I think you know the subject better than me 😛) Ultimately, I think currently the main problem with all possible implementations of the BottomSheet is the "no empty content bug" (+ material theme but we will wait for M3 impl 🙏). Maybe I missed something? (I join you a demo back gesture vs click outside animation)
506 Views