FlexibleBottomAppBar

Functions summary

Unit
@ExperimentalMaterial3ExpressiveApi
@Composable
FlexibleBottomAppBar(
    modifier: Modifier,
    containerColor: Color,
    contentColor: Color,
    contentPadding: PaddingValues,
    horizontalArrangement: Arrangement.Horizontal,
    expandedHeight: Dp,
    windowInsets: WindowInsets,
    scrollBehavior: BottomAppBarScrollBehavior?,
    content: @Composable RowScope.() -> Unit
)

Material Design flexible bottom app bar

Cmn

Functions

FlexibleBottomAppBar

@ExperimentalMaterial3ExpressiveApi
@Composable
fun FlexibleBottomAppBar(
    modifier: Modifier = Modifier,
    containerColor: Color = BottomAppBarDefaults.containerColor,
    contentColor: Color = contentColorFor(containerColor),
    contentPadding: PaddingValues = BottomAppBarDefaults.FlexibleContentPadding,
    horizontalArrangement: Arrangement.Horizontal = BottomAppBarDefaults.FlexibleHorizontalArrangement,
    expandedHeight: Dp = BottomAppBarDefaults.FlexibleBottomAppBarHeight,
    windowInsets: WindowInsets = BottomAppBarDefaults.windowInsets,
    scrollBehavior: BottomAppBarScrollBehavior? = null,
    content: @Composable RowScope.() -> Unit
): Unit

Material Design flexible bottom app bar

A flexible bottom app bar displays navigation and key actions at the bottom of small screens.

This variation of the Bottom app bar has a horizontalArrangement parameter for controlling the way the content is arranged. Also, it allows more flexibility in controlling the bar's expanded height with an expandedHeight value.

If you are interested in displaying a FloatingActionButton, consider using another overload that takes a FloatingActionButton parameter.

Also see NavigationBar.

A bottom app bar that specifies an horizontalArrangement and uses a scrollBehavior to customize its nested scrolling behavior when working in conjunction with a scrolling content looks like:

import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material.icons.automirrored.filled.ArrowForward
import androidx.compose.material.icons.filled.Add
import androidx.compose.material.icons.filled.Check
import androidx.compose.material.icons.filled.Edit
import androidx.compose.material.icons.filled.Favorite
import androidx.compose.material.icons.filled.MoreVert
import androidx.compose.material3.AppBarRow
import androidx.compose.material3.BottomAppBar
import androidx.compose.material3.BottomAppBarDefaults
import androidx.compose.material3.FlexibleBottomAppBar
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.PlainTooltip
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.unit.dp

val icons =
    listOf(
        Icons.AutoMirrored.Filled.ArrowBack,
        Icons.AutoMirrored.Filled.ArrowForward,
        Icons.Filled.Add,
        Icons.Filled.Check,
        Icons.Filled.Edit,
        Icons.Filled.Favorite,
    )
val items = listOf("Back", "Forward", "Add", "Check", "Edit", "Favorite")
FlexibleBottomAppBar(
    contentPadding = PaddingValues(horizontal = 96.dp),
    horizontalArrangement = BottomAppBarDefaults.FlexibleFixedHorizontalArrangement,
) {
    AppBarRow(
        overflowIndicator = { menuState ->
            TooltipBox(
                positionProvider =
                    TooltipDefaults.rememberTooltipPositionProvider(
                        TooltipAnchorPosition.Above
                    ),
                tooltip = { PlainTooltip { Text("Overflow") } },
                state = rememberTooltipState(),
            ) {
                IconButton(
                    onClick = {
                        if (menuState.isShowing) {
                            menuState.dismiss()
                        } else {
                            menuState.show()
                        }
                    }
                ) {
                    Icon(imageVector = Icons.Filled.MoreVert, contentDescription = "Overflow")
                }
            }
        }
    ) {
        items.forEachIndexed { index, item ->
            clickableItem(
                onClick = { /* doSomething() */ },
                icon = { Icon(icons[index], contentDescription = item) },
                label = item,
            )
        }
    }
}
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material.icons.automirrored.filled.ArrowForward
import androidx.compose.material.icons.filled.Add
import androidx.compose.material.icons.filled.Check
import androidx.compose.material.icons.filled.Edit
import androidx.compose.material3.BottomAppBar
import androidx.compose.material3.BottomAppBarDefaults
import androidx.compose.material3.FilledIconButton
import androidx.compose.material3.FlexibleBottomAppBar
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.Modifier
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.unit.dp

val scrollBehavior = BottomAppBarDefaults.exitAlwaysScrollBehavior()
val icons =
    listOf(
        Icons.AutoMirrored.Filled.ArrowBack,
        Icons.AutoMirrored.Filled.ArrowForward,
        Icons.Filled.Add,
        Icons.Filled.Check,
        Icons.Filled.Edit,
    )
val buttons = listOf("Back", "Forward", "Add", "Check", "Edit")

Scaffold(
    modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
    bottomBar = {
        FlexibleBottomAppBar(
            horizontalArrangement = Arrangement.SpaceAround,
            contentPadding = PaddingValues(horizontal = 0.dp),
            scrollBehavior = scrollBehavior,
            content = {
                buttons.forEachIndexed { index, button ->
                    TooltipBox(
                        positionProvider =
                            TooltipDefaults.rememberTooltipPositionProvider(
                                TooltipAnchorPosition.Above
                            ),
                        tooltip = { PlainTooltip { Text(button) } },
                        state = rememberTooltipState(),
                    ) {
                        if (index == 2) {
                            FilledIconButton(
                                modifier = Modifier.width(56.dp),
                                onClick = { /* doSomething() */ },
                            ) {
                                Icon(icons[index], contentDescription = button)
                            }
                        } else {
                            IconButton(onClick = { /* doSomething() */ }) {
                                Icon(icons[index], contentDescription = button)
                            }
                        }
                    }
                }
            },
        )
    },
    content = { innerPadding ->
        LazyColumn(
            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.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material.icons.automirrored.filled.ArrowForward
import androidx.compose.material.icons.filled.Add
import androidx.compose.material.icons.filled.Check
import androidx.compose.material.icons.filled.Edit
import androidx.compose.material3.BottomAppBar
import androidx.compose.material3.BottomAppBarDefaults
import androidx.compose.material3.FilledIconButton
import androidx.compose.material3.FlexibleBottomAppBar
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.Modifier
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.unit.dp

val scrollBehavior = BottomAppBarDefaults.exitAlwaysScrollBehavior()
val icons =
    listOf(
        Icons.AutoMirrored.Filled.ArrowBack,
        Icons.AutoMirrored.Filled.ArrowForward,
        Icons.Filled.Add,
        Icons.Filled.Check,
        Icons.Filled.Edit,
    )
val buttons = listOf("Back", "Forward", "Add", "Check", "Edit")
Scaffold(
    modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
    bottomBar = {
        FlexibleBottomAppBar(
            horizontalArrangement = Arrangement.SpaceBetween,
            scrollBehavior = scrollBehavior,
            content = {
                buttons.forEachIndexed { index, button ->
                    TooltipBox(
                        positionProvider =
                            TooltipDefaults.rememberTooltipPositionProvider(
                                TooltipAnchorPosition.Above
                            ),
                        tooltip = { PlainTooltip { Text(button) } },
                        state = rememberTooltipState(),
                    ) {
                        if (index == 2) {
                            FilledIconButton(
                                modifier = Modifier.width(56.dp),
                                onClick = { /* doSomething() */ },
                            ) {
                                Icon(icons[index], contentDescription = button)
                            }
                        } else {
                            IconButton(onClick = { /* doSomething() */ }) {
                                Icon(icons[index], contentDescription = button)
                            }
                        }
                    }
                }
            },
        )
    },
    content = { innerPadding ->
        LazyColumn(
            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.PaddingValues
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material.icons.automirrored.filled.ArrowForward
import androidx.compose.material.icons.filled.Add
import androidx.compose.material.icons.filled.Check
import androidx.compose.material.icons.filled.Edit
import androidx.compose.material3.BottomAppBar
import androidx.compose.material3.BottomAppBarDefaults
import androidx.compose.material3.FilledIconButton
import androidx.compose.material3.FlexibleBottomAppBar
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.Modifier
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.unit.dp

val scrollBehavior = BottomAppBarDefaults.exitAlwaysScrollBehavior()
val icons =
    listOf(
        Icons.AutoMirrored.Filled.ArrowBack,
        Icons.AutoMirrored.Filled.ArrowForward,
        Icons.Filled.Add,
        Icons.Filled.Check,
        Icons.Filled.Edit,
    )
val buttons = listOf("Back", "Forward", "Add", "Check", "Edit")
Scaffold(
    modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
    bottomBar = {
        FlexibleBottomAppBar(
            horizontalArrangement = Arrangement.SpaceEvenly,
            contentPadding = PaddingValues(horizontal = 0.dp),
            scrollBehavior = scrollBehavior,
            content = {
                buttons.forEachIndexed { index, button ->
                    TooltipBox(
                        positionProvider =
                            TooltipDefaults.rememberTooltipPositionProvider(
                                TooltipAnchorPosition.Above
                            ),
                        tooltip = { PlainTooltip { Text(button) } },
                        state = rememberTooltipState(),
                    ) {
                        if (index == 2) {
                            FilledIconButton(
                                modifier = Modifier.width(56.dp),
                                onClick = { /* doSomething() */ },
                            ) {
                                Icon(icons[index], contentDescription = button)
                            }
                        } else {
                            IconButton(onClick = { /* doSomething() */ }) {
                                Icon(icons[index], contentDescription = button)
                            }
                        }
                    }
                }
            },
        )
    },
    content = { innerPadding ->
        LazyColumn(
            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.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material.icons.automirrored.filled.ArrowForward
import androidx.compose.material.icons.filled.Add
import androidx.compose.material.icons.filled.Check
import androidx.compose.material.icons.filled.Edit
import androidx.compose.material3.BottomAppBar
import androidx.compose.material3.BottomAppBarDefaults
import androidx.compose.material3.FilledIconButton
import androidx.compose.material3.FlexibleBottomAppBar
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.Modifier
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.unit.dp

val scrollBehavior = BottomAppBarDefaults.exitAlwaysScrollBehavior()
val icons =
    listOf(
        Icons.AutoMirrored.Filled.ArrowBack,
        Icons.AutoMirrored.Filled.ArrowForward,
        Icons.Filled.Add,
        Icons.Filled.Check,
        Icons.Filled.Edit,
    )
val buttons = listOf("Back", "Forward", "Add", "Check", "Edit")
Scaffold(
    modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
    bottomBar = {
        FlexibleBottomAppBar(
            horizontalArrangement = BottomAppBarDefaults.FlexibleFixedHorizontalArrangement,
            scrollBehavior = scrollBehavior,
            content = {
                buttons.forEachIndexed { index, button ->
                    TooltipBox(
                        positionProvider =
                            TooltipDefaults.rememberTooltipPositionProvider(
                                TooltipAnchorPosition.Above
                            ),
                        tooltip = { PlainTooltip { Text(button) } },
                        state = rememberTooltipState(),
                    ) {
                        if (index == 2) {
                            FilledIconButton(
                                modifier = Modifier.width(56.dp),
                                onClick = { /* doSomething() */ },
                            ) {
                                Icon(icons[index], contentDescription = button)
                            }
                        } else {
                            IconButton(onClick = { /* doSomething() */ }) {
                                Icon(icons[index], contentDescription = button)
                            }
                        }
                    }
                }
            },
        )
    },
    content = { innerPadding ->
        LazyColumn(
            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.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material.icons.automirrored.filled.ArrowForward
import androidx.compose.material.icons.filled.Add
import androidx.compose.material.icons.filled.Check
import androidx.compose.material.icons.filled.Edit
import androidx.compose.material3.BottomAppBar
import androidx.compose.material3.BottomAppBarDefaults
import androidx.compose.material3.FilledIconButton
import androidx.compose.material3.FlexibleBottomAppBar
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.Modifier
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.unit.dp

val scrollBehavior = BottomAppBarDefaults.exitAlwaysScrollBehavior()
val icons =
    listOf(
        Icons.AutoMirrored.Filled.ArrowBack,
        Icons.AutoMirrored.Filled.ArrowForward,
        Icons.Filled.Add,
        Icons.Filled.Check,
        Icons.Filled.Edit,
    )
val buttons = listOf("Back", "Forward", "Add", "Check", "Edit")
Scaffold(
    modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
    bottomBar = {
        FlexibleBottomAppBar(
            horizontalArrangement = BottomAppBarDefaults.FlexibleFixedHorizontalArrangement,
            scrollBehavior = scrollBehavior,
            containerColor =
                MaterialTheme.colorScheme.primaryContainer, // TODO(b/356885344): tokens
            content = {
                buttons.forEachIndexed { index, button ->
                    TooltipBox(
                        positionProvider =
                            TooltipDefaults.rememberTooltipPositionProvider(
                                TooltipAnchorPosition.Above
                            ),
                        tooltip = { PlainTooltip { Text(button) } },
                        state = rememberTooltipState(),
                    ) {
                        if (index == 2) {
                            FilledIconButton(
                                modifier = Modifier.width(56.dp),
                                onClick = { /* doSomething() */ },
                            ) {
                                Icon(icons[index], contentDescription = button)
                            }
                        } else {
                            IconButton(onClick = { /* doSomething() */ }) {
                                Icon(icons[index], contentDescription = button)
                            }
                        }
                    }
                }
            },
        )
    },
    content = { innerPadding ->
        LazyColumn(
            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
modifier: Modifier = Modifier

the Modifier to be applied to this BottomAppBar

containerColor: Color = BottomAppBarDefaults.containerColor

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

contentColor: Color = contentColorFor(containerColor)

the preferred color for content inside this BottomAppBar. Defaults to either the matching content color for containerColor, or to the current LocalContentColor if containerColor is not a color from the theme.

contentPadding: PaddingValues = BottomAppBarDefaults.FlexibleContentPadding

the padding applied to the content of this BottomAppBar

horizontalArrangement: Arrangement.Horizontal = BottomAppBarDefaults.FlexibleHorizontalArrangement

the horizontal arrangement of the content inside this BottomAppBar

expandedHeight: Dp = BottomAppBarDefaults.FlexibleBottomAppBarHeight

the maximum height this bottom bar can reach when fully expanded. If a scrollBehavior is provided, the bar might collapse or expand based on scrolling. In that case, this value sets the upper limit for the bar's height during expansion. This Dp value must be specified, finite, and greater than zero; otherwise, BottomAppBarDefaults.FlexibleBottomAppBarHeight will be used as a default. In case the scrollBehavior is null, this value will simply be the fixed height of the bottom bar.

windowInsets: WindowInsets = BottomAppBarDefaults.windowInsets

a window insets that app bar will respect.

scrollBehavior: BottomAppBarScrollBehavior? = null

a BottomAppBarScrollBehavior which holds various offset values that will be applied by this bottom app bar to set up its height. A scroll behavior is designed to work in conjunction with a scrolled content to change the bottom app bar appearance as the content scrolls. Note that the bottom app bar will not react to scrolling in case a touch exploration service (e.g., TalkBack) is active. See BottomAppBarScrollBehavior.nestedScrollConnection.

content: @Composable RowScope.() -> Unit

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