Not able to use rememberScaffoldState() in android compose Material3
S

6

43

I want to use

rememberScaffoldState()

in android material3 compose, but not able to use it.

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun AppFeatureScreen(viewModel: AppFeatureViewModel = viewModel()) {
    val scaffoldState = rememberScaffoldState()
    Scaffold() {

    }
}
Startle answered 5/3, 2022 at 15:38 Comment(3)
currently material3 doesn't support both snackbars and a driver in scaffold, so there's nothing to manage with the state. I don't know whether it was removed by material 3 or just not yet implemented in Compose (it's still alpha). I suggest you asking maintainersSse
Seems like it's not going to get [fixed] :((issuetracker.google.com/issues/185097403) "We decided to explicitly remove drawer in material3's scaffold. The reason being that Scaffolds are usually used on the per screen or per set of screens basis, where drawer is usually a app-wide entity. They are at sifferent layers and should not be mixed. you can easily add a drawer by wrapping it your scaffold with NavigationDrawer component."Echovirus
I need to use rememberScaffoldState to show snackBar in Material 3 using Jetpack Compose. How to do that?Dome
M
23

Hello according to Google documents, you can do this: https://developer.android.com/reference/kotlin/androidx/compose/material3/package-summary.html#Snackbar(androidx.compose.material3.SnackbarData,androidx.compose.ui.Modifier,kotlin.Boolean,androidx.compose.ui.graphics.Shape,androidx.compose.ui.graphics.Color,androidx.compose.ui.graphics.Color,androidx.compose.ui.graphics.Color,androidx.compose.ui.graphics.Color,androidx.compose.ui.graphics.Color)

import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.material3.ExtendedFloatingActionButton
import androidx.compose.material3.Scaffold
import androidx.compose.material3.SnackbarHost
import androidx.compose.material3.SnackbarHostState
import androidx.compose.material3.Text
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope

val snackbarHostState = remember { SnackbarHostState() }
val scope = rememberCoroutineScope()
Scaffold(
    snackbarHost = { SnackbarHost(snackbarHostState) },
    floatingActionButton = {
        var clickCount by remember { mutableStateOf(0) }
        ExtendedFloatingActionButton(
            onClick = {
                // show snackbar as a suspend function
                scope.launch {
                    snackbarHostState.showSnackbar(
                        "Snackbar # ${++clickCount}"
                    )
                }
            }
        ) { Text("Show snackbar") }
    },
    content = { innerPadding ->
        Text(
            text = "Body content",
            modifier = Modifier.padding(innerPadding).fillMaxSize().wrapContentSize()
        )
    }
)
Methaemoglobin answered 9/8, 2022 at 1:32 Comment(0)
N
23

rememberScaffoldState was removed in material 3, the migration docs reads

The M2 ScaffoldState class no longer exists in M3 as it contains a drawerState parameter which is no longer needed. To show snackbars with the M3 Scaffold, use SnackbarHostState instead:

So this is how you would show a snackbar in material 3.

import androidx.compose.material3.Scaffold
import androidx.compose.material3.SnackbarHost
import androidx.compose.material3.SnackbarHostState

val snackbarHostState = remember { SnackbarHostState() }
val scope = rememberCoroutineScope()

Scaffold(
    snackbarHost = { SnackbarHost(snackbarHostState) },
    content = {
        …
        Button(
          onClick = {
            scope.launch {
              snackbarHostState.showSnackbar(
                 message = "Hey this is a snackbar",
                 actionLabel = "Click me",
                 duration = SnackbarDuration.Short
              )
            }
          })
           {
             Text(text = "Click me")
           }
    }
)
Nesmith answered 26/7, 2023 at 12:36 Comment(0)
T
9

You need to remember the SnackbarHostState() and provide a SnackbarHost to the Scaffold so that you can show a snackbar.

val snackbarHostState = remember { SnackbarHostState() }

Scaffold(
    ...
    snackbarHost = { SnackbarHost(hostState = snackbarHostState) }
    ...
)

Then you can use snackbarHostState.showSnackbar to show snackbar.

Tisza answered 20/3, 2023 at 5:16 Comment(0)
B
3

I checked NowInAndroid Compose sample project and this is how it showed a snackBar

    val snackbarHostState = remember { SnackbarHostState() }

    
    LaunchedEffect(isOffline) {
        if (isOffline) {
            snackbarHostState.showSnackbar(
                message = notConnectedMessage,
                duration = Indefinite,
            )
        }
    }

there is no need to use it inside a scaffold

Bolster answered 15/3, 2023 at 14:30 Comment(0)
C
3

If you need to show snackbars inside your scaffold. Use the code below:

val snackbarHostState = remember { SnackbarHostState() }

and inject in your Scaffold using:

Scaffold(
    snackbarHost = { SnackbarHost(snackbarHostState) },
    content = {
        …
        scope.launch {
            snackbarHostState.showSnackbar(…)
        }
    }
)
Cyclohexane answered 30/7, 2023 at 23:59 Comment(0)
P
2
class MainActivity : ComponentActivity() {
@OptIn(ExperimentalMaterial3Api::class)
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContent {
        var textFieldState by remember {
            mutableStateOf("")
        }
        val snackbarHostState = remember { SnackbarHostState() }
        val scope = rememberCoroutineScope()
        Scaffold(Modifier.fillMaxSize(), snackbarHost = {
            SnackbarHost(snackbarHostState) { data ->
                Snackbar(
                    modifier = Modifier
                        .padding(12.dp)
                ) {
                    Text(data.visuals.message)
                }
            }
        }) {
            Column(
                modifier = Modifier
                    .padding(it)
                    .fillMaxSize(),
                horizontalAlignment = Alignment.CenterHorizontally,
                verticalArrangement = Arrangement.Center
            ) {
                TextField(
                    value = textFieldState,
                    label = { Text("Enter your name") },
                    onValueChange = {
                        textFieldState = it
                    },
                    singleLine = true,
                    modifier = Modifier.fillMaxWidth()
                )
                Spacer(modifier = Modifier.height(16.dp))
                Button(onClick = {
                    scope.launch {
                        snackbarHostState.showSnackbar("My name is $textFieldState")
                    }
                }) {
                    Text("Show my name")
                }


            }
        }
    }
}

}

Pivot answered 23/5, 2023 at 9:11 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.