HorizontalFloatingToolbar

Functions summary

Unit
@ExperimentalMaterial3ExpressiveApi
@Composable
HorizontalFloatingToolbar(
    expanded: Boolean,
    modifier: Modifier,
    colors: FloatingToolbarColors,
    contentPadding: PaddingValues,
    scrollBehavior: FloatingToolbarScrollBehavior?,
    shape: Shape,
    leadingContent: (@Composable RowScope.() -> Unit)?,
    trailingContent: (@Composable RowScope.() -> Unit)?,
    expandedShadowElevation: Dp,
    collapsedShadowElevation: Dp,
    content: @Composable RowScope.() -> Unit
)

A horizontal floating toolbar displays navigation and key actions in a Row.

Cmn
Unit
@ExperimentalMaterial3ExpressiveApi
@Composable
HorizontalFloatingToolbar(
    expanded: Boolean,
    floatingActionButton: @Composable () -> Unit,
    modifier: Modifier,
    colors: FloatingToolbarColors,
    contentPadding: PaddingValues,
    scrollBehavior: FloatingToolbarScrollBehavior?,
    shape: Shape,
    floatingActionButtonPosition: FloatingToolbarHorizontalFabPosition,
    animationSpec: FiniteAnimationSpec<Float>,
    expandedShadowElevation: Dp,
    collapsedShadowElevation: Dp,
    content: @Composable RowScope.() -> Unit
)

A floating toolbar that displays horizontally.

Cmn

Functions

HorizontalFloatingToolbar

@ExperimentalMaterial3ExpressiveApi
@Composable
fun HorizontalFloatingToolbar(
    expanded: Boolean,
    modifier: Modifier = Modifier,
    colors: FloatingToolbarColors = FloatingToolbarDefaults.standardFloatingToolbarColors(),
    contentPadding: PaddingValues = FloatingToolbarDefaults.ContentPadding,
    scrollBehavior: FloatingToolbarScrollBehavior? = null,
    shape: Shape = FloatingToolbarDefaults.ContainerShape,
    leadingContent: (@Composable RowScope.() -> Unit)? = null,
    trailingContent: (@Composable RowScope.() -> Unit)? = null,
    expandedShadowElevation: Dp = FloatingToolbarDefaults.ContainerExpandedElevation,
    collapsedShadowElevation: Dp = FloatingToolbarDefaults.ContainerCollapsedElevation,
    content: @Composable RowScope.() -> Unit
): Unit

A horizontal floating toolbar displays navigation and key actions in a Row. It can be positioned anywhere on the screen and floats over the rest of the content.

Note: This component will stay expanded to maintain the toolbar visibility for users with touch exploration services enabled (e.g., TalkBack).

import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add
import androidx.compose.material3.FilledIconButton
import androidx.compose.material3.FloatingToolbarDefaults.ScreenOffset
import androidx.compose.material3.FloatingToolbarDefaults.floatingToolbarVerticalNestedScroll
import androidx.compose.material3.FloatingToolbarExitDirection.Companion.Bottom
import androidx.compose.material3.HorizontalFloatingToolbar
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.PlainTooltip
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.TooltipAnchorPosition
import androidx.compose.material3.TooltipBox
import androidx.compose.material3.TooltipDefaults
import androidx.compose.material3.rememberTooltipState
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.compose.ui.zIndex

var expanded by rememberSaveable { mutableStateOf(true) }
Scaffold(
    content = { innerPadding ->
        Box(Modifier.padding(innerPadding)) {
            // The toolbar should receive focus before the screen content, so place it first.
            // Make sure to set its zIndex so it's above the screen content visually.
            HorizontalFloatingToolbar(
                modifier =
                    Modifier.align(Alignment.BottomCenter).offset(y = -ScreenOffset).zIndex(1f),
                expanded = expanded,
                leadingContent = { LeadingContent() },
                trailingContent = { TrailingContent() },
                content = {
                    TooltipBox(
                        positionProvider =
                            TooltipDefaults.rememberTooltipPositionProvider(
                                TooltipAnchorPosition.Above
                            ),
                        tooltip = { PlainTooltip { Text("Localized description") } },
                        state = rememberTooltipState(),
                    ) {
                        FilledIconButton(
                            modifier = Modifier.width(64.dp),
                            onClick = { /* doSomething() */ },
                        ) {
                            Icon(Icons.Filled.Add, contentDescription = "Localized description")
                        }
                    }
                },
            )
            LazyColumn(
                // Apply a floatingToolbarVerticalNestedScroll Modifier toggle the expanded
                // state of the HorizontalFloatingToolbar.
                modifier =
                    Modifier.floatingToolbarVerticalNestedScroll(
                        expanded = expanded,
                        onExpand = { expanded = true },
                        onCollapse = { expanded = false },
                    ),
                state = rememberLazyListState(),
                contentPadding = innerPadding,
                verticalArrangement = Arrangement.spacedBy(8.dp),
            ) {
                val list = (0..75).map { it.toString() }
                items(count = list.size) {
                    Text(
                        text = list[it],
                        style = MaterialTheme.typography.bodyLarge,
                        modifier = Modifier.fillMaxWidth().padding(horizontal = 16.dp),
                    )
                }
            }
        }
    }
)
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add
import androidx.compose.material.icons.filled.ArrowUpward
import androidx.compose.material.icons.filled.Download
import androidx.compose.material.icons.filled.Favorite
import androidx.compose.material.icons.filled.Person
import androidx.compose.material3.AppBarRow
import androidx.compose.material3.FilledIconButton
import androidx.compose.material3.FloatingToolbarDefaults.ScreenOffset
import androidx.compose.material3.FloatingToolbarExitDirection.Companion.Bottom
import androidx.compose.material3.HorizontalFloatingToolbar
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.PlainTooltip
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.TooltipAnchorPosition
import androidx.compose.material3.TooltipBox
import androidx.compose.material3.TooltipDefaults
import androidx.compose.material3.rememberTooltipState
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.compose.ui.zIndex

Scaffold(
    content = { innerPadding ->
        Box(Modifier.padding(innerPadding)) {
            // The toolbar should receive focus before the screen content, so place it first.
            // Make sure to set its zIndex so it's above the screen content visually.
            HorizontalFloatingToolbar(
                modifier =
                    Modifier.align(Alignment.BottomCenter).offset(y = -ScreenOffset).zIndex(1f),
                expanded = true,
                leadingContent = { LeadingContent() },
                trailingContent = {
                    AppBarRow {
                        clickableItem(
                            onClick = { /* doSomething() */ },
                            icon = {
                                Icon(
                                    Icons.Filled.Download,
                                    contentDescription = "Localized description",
                                )
                            },
                            label = "Download",
                        )
                        clickableItem(
                            onClick = { /* doSomething() */ },
                            icon = {
                                Icon(
                                    Icons.Filled.Favorite,
                                    contentDescription = "Localized description",
                                )
                            },
                            label = "Favorite",
                        )
                        clickableItem(
                            onClick = { /* doSomething() */ },
                            icon = {
                                Icon(
                                    Icons.Filled.Add,
                                    contentDescription = "Localized description",
                                )
                            },
                            label = "Add",
                        )
                        clickableItem(
                            onClick = { /* doSomething() */ },
                            icon = {
                                Icon(
                                    Icons.Filled.Person,
                                    contentDescription = "Localized description",
                                )
                            },
                            label = "Person",
                        )
                        clickableItem(
                            onClick = { /* doSomething() */ },
                            icon = {
                                Icon(
                                    Icons.Filled.ArrowUpward,
                                    contentDescription = "Localized description",
                                )
                            },
                            label = "ArrowUpward",
                        )
                    }
                },
                content = {
                    TooltipBox(
                        positionProvider =
                            TooltipDefaults.rememberTooltipPositionProvider(
                                TooltipAnchorPosition.Above
                            ),
                        tooltip = { PlainTooltip { Text("Localized description") } },
                        state = rememberTooltipState(),
                    ) {
                        FilledIconButton(
                            modifier = Modifier.width(64.dp),
                            onClick = { /* doSomething() */ },
                        ) {
                            Icon(Icons.Filled.Add, contentDescription = "Localized description")
                        }
                    }
                },
            )
            LazyColumn(
                state = rememberLazyListState(),
                contentPadding = innerPadding,
                verticalArrangement = Arrangement.spacedBy(8.dp),
            ) {
                val list = (0..75).map { it.toString() }
                items(count = list.size) {
                    Text(
                        text = list[it],
                        style = MaterialTheme.typography.bodyLarge,
                        modifier = Modifier.fillMaxWidth().padding(horizontal = 16.dp),
                    )
                }
            }
        }
    }
)
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add
import androidx.compose.material3.FilledIconButton
import androidx.compose.material3.FloatingToolbarDefaults
import androidx.compose.material3.FloatingToolbarDefaults.ScreenOffset
import androidx.compose.material3.FloatingToolbarExitDirection.Companion.Bottom
import androidx.compose.material3.HorizontalFloatingToolbar
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.PlainTooltip
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.TooltipAnchorPosition
import androidx.compose.material3.TooltipBox
import androidx.compose.material3.TooltipDefaults
import androidx.compose.material3.rememberTooltipState
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.unit.dp
import androidx.compose.ui.zIndex

val exitAlwaysScrollBehavior =
    FloatingToolbarDefaults.exitAlwaysScrollBehavior(exitDirection = Bottom)
Scaffold(
    modifier = Modifier.nestedScroll(exitAlwaysScrollBehavior),
    content = { innerPadding ->
        Box(Modifier.padding(innerPadding)) {
            // The toolbar should receive focus before the screen content, so place it first.
            // Make sure to set its zIndex so it's above the screen content visually.
            HorizontalFloatingToolbar(
                modifier =
                    Modifier.align(Alignment.BottomCenter).offset(y = -ScreenOffset).zIndex(1f),
                expanded = true,
                leadingContent = { LeadingContent() },
                trailingContent = { TrailingContent() },
                content = {
                    TooltipBox(
                        positionProvider =
                            TooltipDefaults.rememberTooltipPositionProvider(
                                TooltipAnchorPosition.Above
                            ),
                        tooltip = { PlainTooltip { Text("Localized description") } },
                        state = rememberTooltipState(),
                    ) {
                        FilledIconButton(
                            modifier = Modifier.width(64.dp),
                            onClick = { /* doSomething() */ },
                        ) {
                            Icon(Icons.Filled.Add, contentDescription = "Localized description")
                        }
                    }
                },
                scrollBehavior = exitAlwaysScrollBehavior,
            )
            LazyColumn(
                state = rememberLazyListState(),
                contentPadding = innerPadding,
                verticalArrangement = Arrangement.spacedBy(8.dp),
            ) {
                val list = (0..75).map { it.toString() }
                items(count = list.size) {
                    Text(
                        text = list[it],
                        style = MaterialTheme.typography.bodyLarge,
                        modifier = Modifier.fillMaxWidth().padding(horizontal = 16.dp),
                    )
                }
            }
        }
    },
)
Parameters
expanded: Boolean

whether the FloatingToolbar is in expanded mode, i.e. showing leadingContent and trailingContent. Note that the toolbar will stay expanded in case a touch exploration service (e.g., TalkBack) is active.

modifier: Modifier = Modifier

the Modifier to be applied to this FloatingToolbar.

colors: FloatingToolbarColors = FloatingToolbarDefaults.standardFloatingToolbarColors()

the colors used for this floating toolbar. There are two predefined FloatingToolbarColors at FloatingToolbarDefaults.standardFloatingToolbarColors and FloatingToolbarDefaults.vibrantFloatingToolbarColors which you can use or modify.

contentPadding: PaddingValues = FloatingToolbarDefaults.ContentPadding

the padding applied to the content of this FloatingToolbar.

scrollBehavior: FloatingToolbarScrollBehavior? = null

a FloatingToolbarScrollBehavior. If null, this FloatingToolbar will not automatically react to scrolling. Note that the toolbar will not react to scrolling in case a touch exploration service (e.g., TalkBack) is active.

shape: Shape = FloatingToolbarDefaults.ContainerShape

the shape used for this FloatingToolbar.

leadingContent: (@Composable RowScope.() -> Unit)? = null

the leading content of this FloatingToolbar. The default layout here is a Row, so content inside will be placed horizontally. Only showing if expanded is true.

trailingContent: (@Composable RowScope.() -> Unit)? = null

the trailing content of this FloatingToolbar. The default layout here is a Row, so content inside will be placed horizontally. Only showing if expanded is true.

expandedShadowElevation: Dp = FloatingToolbarDefaults.ContainerExpandedElevation

the elevation for the shadow below this floating toolbar when expanded.

collapsedShadowElevation: Dp = FloatingToolbarDefaults.ContainerCollapsedElevation

the elevation for the shadow below this floating toolbar when collapsed.

content: @Composable RowScope.() -> Unit

the main content of this FloatingToolbar. The default layout here is a Row, so content inside will be placed horizontally.

HorizontalFloatingToolbar

@ExperimentalMaterial3ExpressiveApi
@Composable
fun HorizontalFloatingToolbar(
    expanded: Boolean,
    floatingActionButton: @Composable () -> Unit,
    modifier: Modifier = Modifier,
    colors: FloatingToolbarColors = FloatingToolbarDefaults.standardFloatingToolbarColors(),
    contentPadding: PaddingValues = FloatingToolbarDefaults.ContentPadding,
    scrollBehavior: FloatingToolbarScrollBehavior? = null,
    shape: Shape = FloatingToolbarDefaults.ContainerShape,
    floatingActionButtonPosition: FloatingToolbarHorizontalFabPosition = FloatingToolbarHorizontalFabPosition.End,
    animationSpec: FiniteAnimationSpec<Float> = FloatingToolbarDefaults.animationSpec(),
    expandedShadowElevation: Dp = FloatingToolbarDefaults.ContainerExpandedElevationWithFab,
    collapsedShadowElevation: Dp = FloatingToolbarDefaults.ContainerCollapsedElevationWithFab,
    content: @Composable RowScope.() -> Unit
): Unit

A floating toolbar that displays horizontally. The bar features its content within a Row, and an adjacent floating icon button. It can be positioned anywhere on the screen, floating above other content, and even in a Scaffold's floating action button slot. Its expanded flag controls the visibility of the actions with a slide animations.

Note: This component will stay expanded to maintain the toolbar visibility for users with touch exploration services enabled (e.g., TalkBack).

In case the toolbar is aligned to the right or the left of the screen, you may apply a FloatingToolbarDefaults.floatingToolbarVerticalNestedScroll Modifier to update the expanded state when scrolling occurs, as this sample shows:

import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add
import androidx.compose.material.icons.filled.Edit
import androidx.compose.material.icons.filled.Favorite
import androidx.compose.material.icons.filled.MoreVert
import androidx.compose.material.icons.filled.Person
import androidx.compose.material3.FloatingToolbarDefaults
import androidx.compose.material3.FloatingToolbarDefaults.ScreenOffset
import androidx.compose.material3.FloatingToolbarDefaults.floatingToolbarVerticalNestedScroll
import androidx.compose.material3.FloatingToolbarExitDirection.Companion.Bottom
import androidx.compose.material3.FloatingToolbarExitDirection.Companion.End
import androidx.compose.material3.HorizontalFloatingToolbar
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.PlainTooltip
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.TooltipAnchorPosition
import androidx.compose.material3.TooltipBox
import androidx.compose.material3.TooltipDefaults
import androidx.compose.material3.rememberTooltipState
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.focusProperties
import androidx.compose.ui.tooling.preview.datasource.LoremIpsum
import androidx.compose.ui.unit.dp
import androidx.compose.ui.zIndex

var expanded by rememberSaveable { mutableStateOf(true) }
val vibrantColors = FloatingToolbarDefaults.vibrantFloatingToolbarColors()
Scaffold { innerPadding ->
    Box(Modifier.padding(innerPadding)) {
        // The toolbar should receive focus before the screen content for a11y, so place it
        // first. Make sure to set its zIndex so it's above the screen content visually.
        HorizontalFloatingToolbar(
            expanded = expanded,
            floatingActionButton = {
                TooltipBox(
                    positionProvider =
                        TooltipDefaults.rememberTooltipPositionProvider(
                            TooltipAnchorPosition.Above
                        ),
                    tooltip = { PlainTooltip { Text("Localized description") } },
                    state = rememberTooltipState(),
                ) {
                    // Match the FAB to the vibrantColors. See also
                    // StandardFloatingActionButton.
                    FloatingToolbarDefaults.VibrantFloatingActionButton(
                        onClick = { expanded = !expanded }
                    ) {
                        Icon(Icons.Filled.Add, "Localized description")
                    }
                }
            },
            modifier =
                Modifier.align(Alignment.BottomEnd)
                    .offset(x = -ScreenOffset, y = -ScreenOffset)
                    .zIndex(1f),
            colors = vibrantColors,
            content = {
                // Make sure the buttons are not focusable if they are not visible, so that
                // keyboard focus doesn't go to an invisible element on the screen.
                TooltipBox(
                    positionProvider =
                        TooltipDefaults.rememberTooltipPositionProvider(
                            TooltipAnchorPosition.Above
                        ),
                    tooltip = { PlainTooltip { Text("Localized description") } },
                    state = rememberTooltipState(),
                ) {
                    IconButton(
                        onClick = { /* doSomething() */ },
                        Modifier.focusProperties { canFocus = expanded },
                    ) {
                        Icon(Icons.Filled.Person, contentDescription = "Localized description")
                    }
                }
                TooltipBox(
                    positionProvider =
                        TooltipDefaults.rememberTooltipPositionProvider(
                            TooltipAnchorPosition.Above
                        ),
                    tooltip = { PlainTooltip { Text("Localized description") } },
                    state = rememberTooltipState(),
                ) {
                    IconButton(
                        onClick = { /* doSomething() */ },
                        Modifier.focusProperties { canFocus = expanded },
                    ) {
                        Icon(Icons.Filled.Edit, contentDescription = "Localized description")
                    }
                }
                TooltipBox(
                    positionProvider =
                        TooltipDefaults.rememberTooltipPositionProvider(
                            TooltipAnchorPosition.Above
                        ),
                    tooltip = { PlainTooltip { Text("Localized description") } },
                    state = rememberTooltipState(),
                ) {
                    IconButton(
                        onClick = { /* doSomething() */ },
                        Modifier.focusProperties { canFocus = expanded },
                    ) {
                        Icon(
                            Icons.Filled.Favorite,
                            contentDescription = "Localized description",
                        )
                    }
                }
                TooltipBox(
                    positionProvider =
                        TooltipDefaults.rememberTooltipPositionProvider(
                            TooltipAnchorPosition.Above
                        ),
                    tooltip = { PlainTooltip { Text("Localized description") } },
                    state = rememberTooltipState(),
                ) {
                    IconButton(
                        onClick = { /* doSomething() */ },
                        Modifier.focusProperties { canFocus = expanded },
                    ) {
                        Icon(
                            Icons.Filled.MoreVert,
                            contentDescription = "Localized description",
                        )
                    }
                }
            },
        )
        Column(
            Modifier.fillMaxWidth()
                .padding(horizontal = 16.dp)
                // Apply a floatingToolbarVerticalNestedScroll Modifier to the Column to toggle
                // the expanded state of the HorizontalFloatingToolbar.
                .floatingToolbarVerticalNestedScroll(
                    expanded = expanded,
                    onExpand = { expanded = true },
                    onCollapse = { expanded = false },
                )
                .verticalScroll(rememberScrollState())
        ) {
            Text(text = remember { LoremIpsum().values.first() })
        }
    }
}

In case the toolbar is positioned along a center edge of the screen (like top or bottom center), it's recommended to maintain the expanded state on scroll and to attach a scrollBehavior in order to hide or show the entire component, as this sample shows:

import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add
import androidx.compose.material.icons.filled.Edit
import androidx.compose.material.icons.filled.Favorite
import androidx.compose.material.icons.filled.MoreVert
import androidx.compose.material.icons.filled.Person
import androidx.compose.material3.FloatingToolbarDefaults
import androidx.compose.material3.FloatingToolbarDefaults.ScreenOffset
import androidx.compose.material3.FloatingToolbarExitDirection.Companion.Bottom
import androidx.compose.material3.HorizontalFloatingToolbar
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.PlainTooltip
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.TooltipAnchorPosition
import androidx.compose.material3.TooltipBox
import androidx.compose.material3.TooltipDefaults
import androidx.compose.material3.rememberTooltipState
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.tooling.preview.datasource.LoremIpsum
import androidx.compose.ui.unit.dp
import androidx.compose.ui.zIndex

val exitAlwaysScrollBehavior =
    FloatingToolbarDefaults.exitAlwaysScrollBehavior(exitDirection = Bottom)
val vibrantColors = FloatingToolbarDefaults.vibrantFloatingToolbarColors()
Scaffold(modifier = Modifier.nestedScroll(exitAlwaysScrollBehavior)) { innerPadding ->
    Box(Modifier.padding(innerPadding)) {
        // The toolbar should receive focus before the screen content for a11y, so place it
        // first. Make sure to set its zIndex so it's above the screen content visually.
        HorizontalFloatingToolbar(
            // Always expanded as the toolbar is bottom-centered. We will use a
            // FloatingToolbarScrollBehavior to hide both the toolbar and its FAB on scroll.
            expanded = true,
            floatingActionButton = {
                TooltipBox(
                    positionProvider =
                        TooltipDefaults.rememberTooltipPositionProvider(
                            TooltipAnchorPosition.Above
                        ),
                    tooltip = { PlainTooltip { Text("Localized description") } },
                    state = rememberTooltipState(),
                ) {
                    // Match the FAB to the vibrantColors. See also
                    // StandardFloatingActionButton.
                    FloatingToolbarDefaults.VibrantFloatingActionButton(
                        onClick = { /* doSomething() */ }
                    ) {
                        Icon(Icons.Filled.Add, "Localized description")
                    }
                }
            },
            modifier =
                Modifier.align(Alignment.BottomCenter).offset(y = -ScreenOffset).zIndex(1f),
            colors = vibrantColors,
            scrollBehavior = exitAlwaysScrollBehavior,
            content = {
                TooltipBox(
                    positionProvider =
                        TooltipDefaults.rememberTooltipPositionProvider(
                            TooltipAnchorPosition.Above
                        ),
                    tooltip = { PlainTooltip { Text("Localized description") } },
                    state = rememberTooltipState(),
                ) {
                    IconButton(onClick = { /* doSomething() */ }) {
                        Icon(Icons.Filled.Person, contentDescription = "Localized description")
                    }
                }
                TooltipBox(
                    positionProvider =
                        TooltipDefaults.rememberTooltipPositionProvider(
                            TooltipAnchorPosition.Above
                        ),
                    tooltip = { PlainTooltip { Text("Localized description") } },
                    state = rememberTooltipState(),
                ) {
                    IconButton(onClick = { /* doSomething() */ }) {
                        Icon(Icons.Filled.Edit, contentDescription = "Localized description")
                    }
                }
                TooltipBox(
                    positionProvider =
                        TooltipDefaults.rememberTooltipPositionProvider(
                            TooltipAnchorPosition.Above
                        ),
                    tooltip = { PlainTooltip { Text("Localized description") } },
                    state = rememberTooltipState(),
                ) {
                    IconButton(onClick = { /* doSomething() */ }) {
                        Icon(
                            Icons.Filled.Favorite,
                            contentDescription = "Localized description",
                        )
                    }
                }
                TooltipBox(
                    positionProvider =
                        TooltipDefaults.rememberTooltipPositionProvider(
                            TooltipAnchorPosition.Above
                        ),
                    tooltip = { PlainTooltip { Text("Localized description") } },
                    state = rememberTooltipState(),
                ) {
                    IconButton(onClick = { /* doSomething() */ }) {
                        Icon(
                            Icons.Filled.MoreVert,
                            contentDescription = "Localized description",
                        )
                    }
                }
            },
        )
        Column(
            Modifier.fillMaxWidth()
                .padding(horizontal = 16.dp)
                .verticalScroll(rememberScrollState())
        ) {
            Text(text = remember { LoremIpsum().values.first() })
        }
    }
}

Note that if your app uses a Snackbar, it's best to position the toolbar in a Scaffold's FAB slot. This ensures the Snackbar appears above the toolbar, preventing any visual overlap or interference. See this sample:

import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add
import androidx.compose.material.icons.filled.Edit
import androidx.compose.material.icons.filled.Favorite
import androidx.compose.material.icons.filled.MoreVert
import androidx.compose.material.icons.filled.Person
import androidx.compose.material3.FabPosition
import androidx.compose.material3.FloatingToolbarDefaults
import androidx.compose.material3.FloatingToolbarDefaults.floatingToolbarVerticalNestedScroll
import androidx.compose.material3.FloatingToolbarExitDirection.Companion.End
import androidx.compose.material3.HorizontalFloatingToolbar
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.PlainTooltip
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.TooltipAnchorPosition
import androidx.compose.material3.TooltipBox
import androidx.compose.material3.TooltipDefaults
import androidx.compose.material3.rememberTooltipState
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.focusProperties
import androidx.compose.ui.tooling.preview.datasource.LoremIpsum
import androidx.compose.ui.unit.dp

var expanded by rememberSaveable { mutableStateOf(true) }
val vibrantColors = FloatingToolbarDefaults.vibrantFloatingToolbarColors()
Scaffold(
    floatingActionButton = {
        HorizontalFloatingToolbar(
            expanded = expanded,
            floatingActionButton = {
                TooltipBox(
                    positionProvider =
                        TooltipDefaults.rememberTooltipPositionProvider(
                            TooltipAnchorPosition.Above
                        ),
                    tooltip = { PlainTooltip { Text("Localized description") } },
                    state = rememberTooltipState(),
                ) {
                    // Match the FAB to the vibrantColors. See also
                    // StandardFloatingActionButton.
                    FloatingToolbarDefaults.VibrantFloatingActionButton(
                        onClick = { expanded = !expanded }
                    ) {
                        Icon(Icons.Filled.Add, "Localized description")
                    }
                }
            },
            colors = vibrantColors,
            content = {
                // Make sure the buttons are not focusable if they are not visible, so that
                // keyboard focus doesn't go to an invisible element on the screen.
                TooltipBox(
                    positionProvider =
                        TooltipDefaults.rememberTooltipPositionProvider(
                            TooltipAnchorPosition.Above
                        ),
                    tooltip = { PlainTooltip { Text("Localized description") } },
                    state = rememberTooltipState(),
                ) {
                    IconButton(
                        onClick = { /* doSomething() */ },
                        Modifier.focusProperties { canFocus = expanded },
                    ) {
                        Icon(Icons.Filled.Person, contentDescription = "Localized description")
                    }
                }
                TooltipBox(
                    positionProvider =
                        TooltipDefaults.rememberTooltipPositionProvider(
                            TooltipAnchorPosition.Above
                        ),
                    tooltip = { PlainTooltip { Text("Localized description") } },
                    state = rememberTooltipState(),
                ) {
                    IconButton(
                        onClick = { /* doSomething() */ },
                        Modifier.focusProperties { canFocus = expanded },
                    ) {
                        Icon(Icons.Filled.Edit, contentDescription = "Localized description")
                    }
                }
                TooltipBox(
                    positionProvider =
                        TooltipDefaults.rememberTooltipPositionProvider(
                            TooltipAnchorPosition.Above
                        ),
                    tooltip = { PlainTooltip { Text("Localized description") } },
                    state = rememberTooltipState(),
                ) {
                    IconButton(
                        onClick = { /* doSomething() */ },
                        Modifier.focusProperties { canFocus = expanded },
                    ) {
                        Icon(
                            Icons.Filled.Favorite,
                            contentDescription = "Localized description",
                        )
                    }
                }
                TooltipBox(
                    positionProvider =
                        TooltipDefaults.rememberTooltipPositionProvider(
                            TooltipAnchorPosition.Above
                        ),
                    tooltip = { PlainTooltip { Text("Localized description") } },
                    state = rememberTooltipState(),
                ) {
                    IconButton(
                        onClick = { /* doSomething() */ },
                        Modifier.focusProperties { canFocus = expanded },
                    ) {
                        Icon(
                            Icons.Filled.MoreVert,
                            contentDescription = "Localized description",
                        )
                    }
                }
            },
        )
    },
    // When setting this to `FabPosition.Start` remember to set a
    // `floatingActionButtonPosition = FloatingToolbarHorizontalFabPosition.Start` at the
    // HorizontalFloatingToolbar as well.
    floatingActionButtonPosition = FabPosition.End,
) { innerPadding ->
    Box(Modifier.padding(innerPadding)) {
        Column(
            Modifier.fillMaxWidth()
                .padding(horizontal = 16.dp)
                // Apply a floatingToolbarVerticalNestedScroll Modifier to the Column to toggle
                // the expanded state of the HorizontalFloatingToolbar.
                .then(
                    Modifier.floatingToolbarVerticalNestedScroll(
                        expanded = expanded,
                        onExpand = { expanded = true },
                        onCollapse = { expanded = false },
                    )
                )
                .verticalScroll(rememberScrollState())
        ) {
            Text(text = remember { LoremIpsum().values.first() })
        }
    }
}
Parameters
expanded: Boolean

whether the floating toolbar is expanded or not. In its expanded state, the FAB and the toolbar content are organized horizontally. Otherwise, only the FAB is visible. Note that the toolbar will stay expanded in case a touch exploration service (e.g., TalkBack) is active.

floatingActionButton: @Composable () -> Unit

a floating action button to be displayed by the toolbar. It's recommended to use a FloatingToolbarDefaults.VibrantFloatingActionButton or FloatingToolbarDefaults.StandardFloatingActionButton that is styled to match the colors. Note that the provided FAB's size is controlled by the floating toolbar and animates according to its state. In case a custom FAB is provided, make sure it's set with a Modifier.fillMaxSize to be sized correctly.

modifier: Modifier = Modifier

the Modifier to be applied to this floating toolbar.

colors: FloatingToolbarColors = FloatingToolbarDefaults.standardFloatingToolbarColors()

the colors used for this floating toolbar. There are two predefined FloatingToolbarColors at FloatingToolbarDefaults.standardFloatingToolbarColors and FloatingToolbarDefaults.vibrantFloatingToolbarColors which you can use or modify. See also floatingActionButton for more information on the right FAB to use for proper styling.

contentPadding: PaddingValues = FloatingToolbarDefaults.ContentPadding

the padding applied to the content of this floating toolbar.

scrollBehavior: FloatingToolbarScrollBehavior? = null

a FloatingToolbarScrollBehavior. If provided, this FloatingToolbar will automatically react to scrolling. If your toolbar is positioned along a center edge of the screen (like top or bottom center), it's best to use this scroll behavior to make the entire toolbar scroll off-screen as the user scrolls. This would prevent the FAB from appearing off-center, which may occur in this case when using the expanded flag to simply expand or collapse the toolbar. Note that the toolbar will not react to scrolling in case a touch exploration service (e.g., TalkBack) is active.

shape: Shape = FloatingToolbarDefaults.ContainerShape

the shape used for this floating toolbar content.

floatingActionButtonPosition: FloatingToolbarHorizontalFabPosition = FloatingToolbarHorizontalFabPosition.End

the position of the floating toolbar's floating action button. By default, the FAB is placed at the end of the toolbar (i.e. aligned to the right in left-to-right layout, or to the left in right-to-left layout).

animationSpec: FiniteAnimationSpec<Float> = FloatingToolbarDefaults.animationSpec()

the animation spec to use for this floating toolbar expand and collapse animation.

expandedShadowElevation: Dp = FloatingToolbarDefaults.ContainerExpandedElevationWithFab

the elevation for the shadow below this floating toolbar when expanded.

collapsedShadowElevation: Dp = FloatingToolbarDefaults.ContainerCollapsedElevationWithFab

the elevation for the shadow below this floating toolbar when collapsed.

content: @Composable RowScope.() -> Unit

the main content of this floating toolbar. The default layout here is a Row, so content inside will be placed horizontally.