JD74
JD74

Reputation: 425

Snackbar doesn't show in Material 3

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

Answers (2)

Zakaraya Ashour
Zakaraya Ashour

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

Maxime Claude
Maxime Claude

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

Related Questions