Reputation: 425
I'm trying material3 and I can't get my snackbar to show. This code worked in material2. When the snackbar is called for the column shifts down like I would expect but it's very brief, much shorter than a short duration snackbar and there is no message.
@Composable
fun Snackbar(snackbarHostState: SnackbarHostState) {
SnackbarHost(
hostState = snackbarHostState,
snackbar = { snackbarData: SnackbarData ->
Card(
shape = RoundedCornerShape(10.dp),
modifier = Modifier
.padding(20.dp)
.wrapContentSize()
) {
Text(text = snackbarData.visuals.message, fontSize = 30.sp)
}
}
)
}
@Composable
fun LaunchSnackbar (snackbarHostState: SnackbarHostState, message: String) {
LaunchedEffect(true) {
snackbarHostState.showSnackbar(message = message)
}
}
val snackbarHostState = remember { SnackbarHostState() }
Snackbar(snackbarHostState)
LaunchSnackbar(snackbarHostState = snackbarHostState, message = "Incorrect")
It looked like the only thing I had to change was
snackbarData.message
snackbarData.visual.message
Not sure what else is wrong.
Upvotes: 2
Views: 1856
Reputation: 61
I have had similar issues with what appears to also be the coroutines being cancelled upon recomposition and snack bars quickly disappearing faster than the designated duration. A solution that I have found to work is to create a scaffold around your NavHost and assign the snackbarhost to this scaffold, executing the launched effect in this composable.
One issue that ive also come across is forgetting that if your snackbar message state is the the same, as in the same message, the LaunchedEffect will not execute since technically your message state didnt change. To solve this in a simple way is to modify your message type to a data class that has a timestamp of the time the message is emitted onto the messages sharedFlow.
@Composable
fun NavHostComposable(
viewModel: ViewModel
) {
val navController = rememberNavController()
val snackbarHostState = remember{SnackbarHostState()}
val snackbarMessages by viewModel.snackbarMessages.collectAsState(initial = null)
LaunchedEffect(key1 = snackbarMessages) {
snackbarMessages?.let { snackBarMessage ->
//Show snackbar message on every non-null value
snackbarHostState.showSnackbar(
message = snackBarMessage.message,
duration = SnackbarDuration.Short
)
}
}
Scaffold(
snackbarHost = { SnackbarHost(snackbarHostState) },
) { innerPadding ->
NavHost(
modifier = Modifier.padding(innerPadding ),
navController = navController,
...
) {
...
}
}
}
Upvotes: 2
Reputation: 995
Please can you share your Scaffold
's code. I would like to see where how you place your SnackBarHost
in your Scaffold
.
If you go to the documentation, we see this:
val snackbarHostState = remember { SnackbarHostState() }
val scope = rememberCoroutineScope()
Scaffold(
snackbarHost = { SnackbarHost(snackbarHostState) },
content = {
…
scope.launch {
snackbarHostState.showSnackbar(…)
}
}
)
This tells me that, from the two lines below (from the code you posted)
Snackbar(snackbarHostState)
LaunchSnackbar(snackbarHostState = snackbarHostState, message = "Incorrect")
we should replace the first line with the Scaffold
to which you should pass your Snackbar(snackbarHostState)
.
So if I repeat the documentation code, it would look something like:
val snackbarHostState = remember { SnackbarHostState() }
val scope = rememberCoroutineScope()
Scaffold(
snackbarHost = { Snackbar(snackbarHostState) },
content = {
…
scope.launch {
snackbarHostState.showSnackbar(…)
}
}
)
LaunchSnackbar(snackbarHostState = snackbarHostState, message = "Incorrect")
Upvotes: 1