{% setvar book_path %}/reference/androidx/_book.yaml{% endsetvar %} {% include "_shared/_reference-head-tags.html" %}

SnackbarKt

public final class SnackbarKt


Summary

Public methods

static final void
@Composable
Snackbar(
    @NonNull SnackbarData snackbarData,
    @NonNull Modifier modifier,
    boolean actionOnNewLine,
    @NonNull Shape shape,
    @NonNull Color containerColor,
    @NonNull Color contentColor,
    @NonNull Color actionColor,
    @NonNull Color actionContentColor,
    @NonNull Color dismissActionContentColor
)

Material Design snackbar.

static final void
@Composable
Snackbar(
    @NonNull Modifier modifier,
    @Composable Function0<Unit> action,
    @Composable Function0<Unit> dismissAction,
    boolean actionOnNewLine,
    @NonNull Shape shape,
    @NonNull Color containerColor,
    @NonNull Color contentColor,
    @NonNull Color actionContentColor,
    @NonNull Color dismissActionContentColor,
    @Composable @NonNull Function0<Unit> content
)

Material Design snackbar.

Public methods

Snackbar

@Composable
public static final void Snackbar(
    @NonNull SnackbarData snackbarData,
    @NonNull Modifier modifier,
    boolean actionOnNewLine,
    @NonNull Shape shape,
    @NonNull Color containerColor,
    @NonNull Color contentColor,
    @NonNull Color actionColor,
    @NonNull Color actionContentColor,
    @NonNull Color dismissActionContentColor
)

Material Design snackbar.

Snackbars provide brief messages about app processes at the bottom of the screen.

Snackbar image

Snackbars inform users of a process that an app has performed or will perform. They appear temporarily, towards the bottom of the screen. They shouldn’t interrupt the user experience, and they don’t require user input to disappear.

A Snackbar can contain a single action. "Dismiss" or "cancel" actions are optional.

Snackbars with an action should not timeout or self-dismiss until the user performs another action. Here, moving the keyboard focus indicator to navigate through interactive elements in a page is not considered an action.

This version of snackbar is designed to work with SnackbarData provided by the SnackbarHost, which is usually used inside of the Scaffold.

This components provides only the visuals of the Snackbar. If you need to show a Snackbar with defaults on the screen, use SnackbarHostState.showSnackbar:

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.Snackbar
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
import androidx.compose.ui.Modifier

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()
        )
    }
)

If you want to customize appearance of the Snackbar, you can pass your own version as a child of the SnackbarHost to the Scaffold:

import androidx.compose.foundation.border
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.ExtendedFloatingActionButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Snackbar
import androidx.compose.material3.SnackbarDuration
import androidx.compose.material3.SnackbarHost
import androidx.compose.material3.SnackbarHostState
import androidx.compose.material3.SnackbarVisuals
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp

class SnackbarVisualsWithError(
    override val message: String,
    val isError: Boolean
) : SnackbarVisuals {
    override val actionLabel: String
        get() = if (isError) "Error" else "OK"
    override val withDismissAction: Boolean
        get() = false
    override val duration: SnackbarDuration
        get() = SnackbarDuration.Indefinite
}

val snackbarHostState = remember { SnackbarHostState() }
val scope = rememberCoroutineScope()
Scaffold(
    snackbarHost = {
        // reuse default SnackbarHost to have default animation and timing handling
        SnackbarHost(snackbarHostState) { data ->
            // custom snackbar with the custom action button color and border
            val isError = (data.visuals as? SnackbarVisualsWithError)?.isError ?: false
            val buttonColor = if (isError) {
                ButtonDefaults.textButtonColors(
                    containerColor = MaterialTheme.colorScheme.errorContainer,
                    contentColor = MaterialTheme.colorScheme.error
                )
            } else {
                ButtonDefaults.textButtonColors(
                    contentColor = MaterialTheme.colorScheme.inversePrimary
                )
            }

            Snackbar(
                modifier = Modifier
                    .border(2.dp, MaterialTheme.colorScheme.secondary)
                    .padding(12.dp),
                action = {
                    TextButton(
                        onClick = { if (isError) data.dismiss() else data.performAction() },
                        colors = buttonColor
                    ) { Text(data.visuals.actionLabel ?: "") }
                }
            ) {
                Text(data.visuals.message)
            }
        }
    },
    floatingActionButton = {
        var clickCount by remember { mutableStateOf(0) }
        ExtendedFloatingActionButton(
            onClick = {
                scope.launch {
                    snackbarHostState.showSnackbar(
                        SnackbarVisualsWithError(
                            "Snackbar # ${++clickCount}",
                            isError = clickCount % 2 != 0
                        )
                    )
                }
            }
        ) { Text("Show snackbar") }
    },
    content = { innerPadding ->
        Text(
            text = "Custom Snackbar Demo",
            modifier = Modifier
                .padding(innerPadding)
                .fillMaxSize()
                .wrapContentSize()
        )
    }
)

When a SnackbarData.visuals sets the Snackbar's duration as SnackbarDuration.Indefinite, it's recommended to display an additional close affordance action. See SnackbarVisuals.withDismissAction:

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.Snackbar
import androidx.compose.material3.SnackbarDuration
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
import androidx.compose.ui.Modifier

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(
                        message = "Snackbar # ${++clickCount}",
                        actionLabel = "Action",
                        withDismissAction = true,
                        duration = SnackbarDuration.Indefinite
                    )
                }
            }
        ) { Text("Show snackbar") }
    },
    content = { innerPadding ->
        Text(
            text = "Body content",
            modifier = Modifier
                .padding(innerPadding)
                .fillMaxSize()
                .wrapContentSize()
        )
    }
)
Parameters
@NonNull SnackbarData snackbarData

data about the current snackbar showing via SnackbarHostState

@NonNull Modifier modifier

the Modifier to be applied to this snackbar

boolean actionOnNewLine

whether or not action should be put on a separate line. Recommended for action with long action text.

@NonNull Shape shape

defines the shape of this snackbar's container

@NonNull Color containerColor

the color used for the background of this snackbar. Use Color.Transparent to have no color.

@NonNull Color contentColor

the preferred color for content inside this snackbar

@NonNull Color actionColor

the color of the snackbar's action

@NonNull Color actionContentColor

the preferred content color for the optional action inside this snackbar. See SnackbarVisuals.actionLabel.

@NonNull Color dismissActionContentColor

the preferred content color for the optional dismiss action inside this snackbar. See SnackbarVisuals.withDismissAction.

Snackbar

@Composable
public static final void Snackbar(
    @NonNull Modifier modifier,
    @Composable Function0<Unit> action,
    @Composable Function0<Unit> dismissAction,
    boolean actionOnNewLine,
    @NonNull Shape shape,
    @NonNull Color containerColor,
    @NonNull Color contentColor,
    @NonNull Color actionContentColor,
    @NonNull Color dismissActionContentColor,
    @Composable @NonNull Function0<Unit> content
)

Material Design snackbar.

Snackbars provide brief messages about app processes at the bottom of the screen.

Snackbar image

Snackbars inform users of a process that an app has performed or will perform. They appear temporarily, towards the bottom of the screen. They shouldn’t interrupt the user experience, and they don’t require user input to disappear.

A Snackbar can contain a single action. "Dismiss" or "cancel" actions are optional.

Snackbars with an action should not timeout or self-dismiss until the user performs another action. Here, moving the keyboard focus indicator to navigate through interactive elements in a page is not considered an action.

This component provides only the visuals of the Snackbar. If you need to show a Snackbar with defaults on the screen, use SnackbarHostState.showSnackbar:

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.Snackbar
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
import androidx.compose.ui.Modifier

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()
        )
    }
)

If you want to customize appearance of the Snackbar, you can pass your own version as a child of the SnackbarHost to the Scaffold:

import androidx.compose.foundation.border
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.ExtendedFloatingActionButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Snackbar
import androidx.compose.material3.SnackbarDuration
import androidx.compose.material3.SnackbarHost
import androidx.compose.material3.SnackbarHostState
import androidx.compose.material3.SnackbarVisuals
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp

class SnackbarVisualsWithError(
    override val message: String,
    val isError: Boolean
) : SnackbarVisuals {
    override val actionLabel: String
        get() = if (isError) "Error" else "OK"
    override val withDismissAction: Boolean
        get() = false
    override val duration: SnackbarDuration
        get() = SnackbarDuration.Indefinite
}

val snackbarHostState = remember { SnackbarHostState() }
val scope = rememberCoroutineScope()
Scaffold(
    snackbarHost = {
        // reuse default SnackbarHost to have default animation and timing handling
        SnackbarHost(snackbarHostState) { data ->
            // custom snackbar with the custom action button color and border
            val isError = (data.visuals as? SnackbarVisualsWithError)?.isError ?: false
            val buttonColor = if (isError) {
                ButtonDefaults.textButtonColors(
                    containerColor = MaterialTheme.colorScheme.errorContainer,
                    contentColor = MaterialTheme.colorScheme.error
                )
            } else {
                ButtonDefaults.textButtonColors(
                    contentColor = MaterialTheme.colorScheme.inversePrimary
                )
            }

            Snackbar(
                modifier = Modifier
                    .border(2.dp, MaterialTheme.colorScheme.secondary)
                    .padding(12.dp),
                action = {
                    TextButton(
                        onClick = { if (isError) data.dismiss() else data.performAction() },
                        colors = buttonColor
                    ) { Text(data.visuals.actionLabel ?: "") }
                }
            ) {
                Text(data.visuals.message)
            }
        }
    },
    floatingActionButton = {
        var clickCount by remember { mutableStateOf(0) }
        ExtendedFloatingActionButton(
            onClick = {
                scope.launch {
                    snackbarHostState.showSnackbar(
                        SnackbarVisualsWithError(
                            "Snackbar # ${++clickCount}",
                            isError = clickCount % 2 != 0
                        )
                    )
                }
            }
        ) { Text("Show snackbar") }
    },
    content = { innerPadding ->
        Text(
            text = "Custom Snackbar Demo",
            modifier = Modifier
                .padding(innerPadding)
                .fillMaxSize()
                .wrapContentSize()
        )
    }
)

For a multiline sample following the Material recommended spec of a maximum of 2 lines, see:

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.Snackbar
import androidx.compose.material3.SnackbarHost
import androidx.compose.material3.SnackbarHostState
import androidx.compose.material3.Text
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.style.TextOverflow

val snackbarHostState = remember { SnackbarHostState() }
val scope = rememberCoroutineScope()
Scaffold(
    snackbarHost = {
        SnackbarHost(snackbarHostState) { data ->
            Snackbar {
                // The Material spec recommends a maximum of 2 lines of text.
                Text(data.visuals.message, maxLines = 2, overflow = TextOverflow.Ellipsis)
            }
        }
    },
    floatingActionButton = {
        ExtendedFloatingActionButton(
            onClick = {
                scope.launch {
                    val longMessage =
                        "Very very very very very very very very very very very very very " +
                            "very very very very very very very very very very very very " +
                            "very very very very very very very very very very long message"
                    snackbarHostState.showSnackbar(longMessage)
                }
            }
        ) { Text("Show snackbar") }
    },
    content = { innerPadding ->
        Text(
            text = "Multiline Snackbar Demo",
            modifier = Modifier
                .padding(innerPadding)
                .fillMaxSize()
                .wrapContentSize()
        )
    }
)
Parameters
@NonNull Modifier modifier

the Modifier to be applied to this snackbar

@Composable Function0<Unit> action

action / button component to add as an action to the snackbar. Consider using ColorScheme.inversePrimary as the color for the action, if you do not have a predefined color you wish to use instead.

@Composable Function0<Unit> dismissAction

action / button component to add as an additional close affordance action when a snackbar is non self-dismissive. Consider using ColorScheme.inverseOnSurface as the color for the action, if you do not have a predefined color you wish to use instead.

boolean actionOnNewLine

whether or not action should be put on a separate line. Recommended for action with long action text.

@NonNull Shape shape

defines the shape of this snackbar's container

@NonNull Color containerColor

the color used for the background of this snackbar. Use Color.Transparent to have no color.

@NonNull Color contentColor

the preferred color for content inside this snackbar

@NonNull Color actionContentColor

the preferred content color for the optional action inside this snackbar

@NonNull Color dismissActionContentColor

the preferred content color for the optional dismissAction inside this snackbar

@Composable @NonNull Function0<Unit> content

content to show information about a process that an app has performed or will perform