BackdropScaffold

Functions summary

Unit
@Composable
BackdropScaffold(
    appBar: @Composable () -> Unit,
    backLayerContent: @Composable () -> Unit,
    frontLayerContent: @Composable () -> Unit,
    modifier: Modifier,
    scaffoldState: BackdropScaffoldState,
    snackbarHost: @Composable (SnackbarHostState) -> Unit,
    gesturesEnabled: Boolean,
    peekHeight: Dp,
    headerHeight: Dp,
    persistentAppBar: Boolean,
    stickyFrontLayer: Boolean,
    backLayerBackgroundColor: Color,
    backLayerContentColor: Color,
    frontLayerShape: Shape,
    frontLayerElevation: Dp,
    frontLayerBackgroundColor: Color,
    frontLayerContentColor: Color,
    frontLayerScrimColor: Color
)

Material Design backdrop

Cmn

Functions

BackdropScaffold

@Composable
fun BackdropScaffold(
    appBar: @Composable () -> Unit,
    backLayerContent: @Composable () -> Unit,
    frontLayerContent: @Composable () -> Unit,
    modifier: Modifier = Modifier,
    scaffoldState: BackdropScaffoldState = rememberBackdropScaffoldState(Concealed),
    snackbarHost: @Composable (SnackbarHostState) -> Unit = { SnackbarHost(it) },
    gesturesEnabled: Boolean = true,
    peekHeight: Dp = BackdropScaffoldDefaults.PeekHeight,
    headerHeight: Dp = BackdropScaffoldDefaults.HeaderHeight,
    persistentAppBar: Boolean = true,
    stickyFrontLayer: Boolean = true,
    backLayerBackgroundColor: Color = MaterialTheme.colors.primary,
    backLayerContentColor: Color = contentColorFor(backLayerBackgroundColor),
    frontLayerShape: Shape = BackdropScaffoldDefaults.frontLayerShape,
    frontLayerElevation: Dp = BackdropScaffoldDefaults.FrontLayerElevation,
    frontLayerBackgroundColor: Color = MaterialTheme.colors.surface,
    frontLayerContentColor: Color = contentColorFor(frontLayerBackgroundColor),
    frontLayerScrimColor: Color = BackdropScaffoldDefaults.frontLayerScrimColor
): Unit

Material Design backdrop

A backdrop appears behind all other surfaces in an app, displaying contextual and actionable content.

Backdrop
image

This component provides an API to put together several material components to construct your screen. For a similar component which implements the basic material design layout strategy with app bars, floating action buttons and navigation drawers, use the standard Scaffold. For similar component that uses a bottom sheet as the centerpiece of the screen, use BottomSheetScaffold.

Either the back layer or front layer can be active at a time. When the front layer is active, it sits at an offset below the top of the screen. This is the peekHeight and defaults to 56dp which is the default app bar height. When the front layer is inactive, it sticks to the height of the back layer's content if stickyFrontLayer is set to true and the height of the front layer exceeds the headerHeight, and otherwise it minimizes to the headerHeight. To switch between the back layer and front layer, you can either swipe on the front layer if gesturesEnabled is set to true or use any of the methods in BackdropScaffoldState.

The scaffold also contains an app bar, which by default is placed above the back layer's content. If persistentAppBar is set to false, then the backdrop will not show the app bar when the back layer is revealed; instead it will switch between the app bar and the provided content with an animation. For best results, the peekHeight should match the app bar height. To show a snackbar, use the method showSnackbar of BackdropScaffoldState.snackbarHostState.

A simple example of a backdrop scaffold looks like this:

import androidx.compose.foundation.clickable
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material.BackdropScaffold
import androidx.compose.material.BackdropValue
import androidx.compose.material.Icon
import androidx.compose.material.IconButton
import androidx.compose.material.ListItem
import androidx.compose.material.Text
import androidx.compose.material.TopAppBar
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Close
import androidx.compose.material.icons.filled.Favorite
import androidx.compose.material.icons.filled.Menu
import androidx.compose.material.rememberBackdropScaffoldState
import androidx.compose.runtime.LaunchedEffect
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

val scope = rememberCoroutineScope()
val selection = remember { mutableStateOf(1) }
val scaffoldState = rememberBackdropScaffoldState(BackdropValue.Concealed)
LaunchedEffect(scaffoldState) { scaffoldState.reveal() }
BackdropScaffold(
    scaffoldState = scaffoldState,
    appBar = {
        TopAppBar(
            title = { Text("Backdrop scaffold") },
            navigationIcon = {
                if (scaffoldState.isConcealed) {
                    IconButton(onClick = { scope.launch { scaffoldState.reveal() } }) {
                        Icon(Icons.Default.Menu, contentDescription = "Localized description")
                    }
                } else {
                    IconButton(onClick = { scope.launch { scaffoldState.conceal() } }) {
                        Icon(Icons.Default.Close, contentDescription = "Localized description")
                    }
                }
            },
            actions = {
                var clickCount by remember { mutableStateOf(0) }
                IconButton(
                    onClick = {
                        // show snackbar as a suspend function
                        scope.launch {
                            scaffoldState.snackbarHostState.showSnackbar(
                                "Snackbar #${++clickCount}"
                            )
                        }
                    }
                ) {
                    Icon(Icons.Default.Favorite, contentDescription = "Localized description")
                }
            },
            elevation = 0.dp,
            backgroundColor = Color.Transparent,
        )
    },
    backLayerContent = {
        LazyColumn {
            items(if (selection.value >= 3) 3 else 5) {
                ListItem(
                    Modifier.clickable {
                        selection.value = it
                        scope.launch { scaffoldState.conceal() }
                    },
                    text = { Text("Select $it") },
                )
            }
        }
    },
    frontLayerContent = {
        Text("Selection: ${selection.value}")
        LazyColumn {
            items(50) {
                ListItem(
                    text = { Text("Item $it") },
                    icon = {
                        Icon(
                            Icons.Default.Favorite,
                            contentDescription = "Localized description",
                        )
                    },
                )
            }
        }
    },
)
Parameters
appBar: @Composable () -> Unit

App bar for the back layer. Make sure that the peekHeight is equal to the height of the app bar, so that the app bar is fully visible. Consider using TopAppBar but set the elevation to 0dp and background color to transparent as a surface is already provided.

backLayerContent: @Composable () -> Unit

The content of the back layer.

frontLayerContent: @Composable () -> Unit

The content of the front layer.

modifier: Modifier = Modifier

Optional Modifier for the root of the scaffold.

scaffoldState: BackdropScaffoldState = rememberBackdropScaffoldState(Concealed)

The state of the scaffold.

snackbarHost: @Composable (SnackbarHostState) -> Unit = { SnackbarHost(it) }

The component hosting the snackbars shown inside the scaffold.

gesturesEnabled: Boolean = true

Whether or not the backdrop can be interacted with by gestures.

peekHeight: Dp = BackdropScaffoldDefaults.PeekHeight

The height of the visible part of the back layer when it is concealed.

headerHeight: Dp = BackdropScaffoldDefaults.HeaderHeight

The minimum height of the front layer when it is inactive.

persistentAppBar: Boolean = true

Whether the app bar should be shown when the back layer is revealed. By default, it will always be shown above the back layer's content. If this is set to false, the back layer will automatically switch between the app bar and its content with an animation.

stickyFrontLayer: Boolean = true

Whether the front layer should stick to the height of the back layer.

backLayerBackgroundColor: Color = MaterialTheme.colors.primary

The background color of the back layer.

backLayerContentColor: Color = contentColorFor(backLayerBackgroundColor)

The preferred content color provided by the back layer to its children. Defaults to the matching content color for backLayerBackgroundColor, or if that is not a color from the theme, this will keep the same content color set above the back layer.

frontLayerShape: Shape = BackdropScaffoldDefaults.frontLayerShape

The shape of the front layer.

frontLayerElevation: Dp = BackdropScaffoldDefaults.FrontLayerElevation

The elevation of the front layer.

frontLayerBackgroundColor: Color = MaterialTheme.colors.surface

The background color of the front layer.

frontLayerContentColor: Color = contentColorFor(frontLayerBackgroundColor)

The preferred content color provided by the back front to its children. Defaults to the matching content color for frontLayerBackgroundColor, or if that is not a color from the theme, this will keep the same content color set above the front layer.

frontLayerScrimColor: Color = BackdropScaffoldDefaults.frontLayerScrimColor

The color of the scrim applied to the front layer when the back layer is revealed. If the color passed is Color.Unspecified, then a scrim will not be applied and interaction with the front layer will not be blocked when the back layer is revealed.