VerticalFloatingToolbar
Common
Component in Material 3 Compose
A vertical floating toolbar displays navigation and key actions in a [Column]. It can be positioned anywhere on the screen and floats over the rest of the content.
Last updated:
Installation
dependencies {
implementation("androidx.compose.material3:material3:1.4.0-alpha07")
}
Overloads
@ExperimentalMaterial3ExpressiveApi
@Composable
fun VerticalFloatingToolbar(
expanded: Boolean,
modifier: Modifier = Modifier,
colors: FloatingToolbarColors = FloatingToolbarDefaults.standardFloatingToolbarColors(),
contentPadding: PaddingValues = FloatingToolbarDefaults.ContentPadding,
scrollBehavior: FloatingToolbarScrollBehavior? = null,
shape: Shape = FloatingToolbarDefaults.ContainerShape,
leadingContent: @Composable (ColumnScope.() -> Unit)? = null,
trailingContent: @Composable (ColumnScope.() -> Unit)? = null,
content: @Composable ColumnScope.() -> Unit
)
Parameters
name | description |
---|---|
expanded | whether the FloatingToolbar is in expanded mode, i.e. showing [leadingContent] and [trailingContent]. |
modifier | the [Modifier] to be applied to this FloatingToolbar. |
colors | 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 | the padding applied to the content of this FloatingToolbar. |
scrollBehavior | a [FloatingToolbarScrollBehavior]. If null, this FloatingToolbar will not automatically react to scrolling. |
shape | the shape used for this FloatingToolbar. |
leadingContent | the leading content of this FloatingToolbar. The default layout here is a [Column], so content inside will be placed vertically. Only showing if [expanded] is true. |
trailingContent | the trailing content of this FloatingToolbar. The default layout here is a [Column], so content inside will be placed vertically. Only showing if [expanded] is true. |
content | the main content of this FloatingToolbar. The default layout here is a [Column], so content inside will be placed vertically. |
@Deprecated(
message = "Use the VerticalFloatingToolbar function that accepts FloatingToolbarColors",
level = DeprecationLevel.HIDDEN
)
@ExperimentalMaterial3ExpressiveApi
@Composable
fun VerticalFloatingToolbar(
expanded: Boolean,
modifier: Modifier = Modifier,
containerColor: Color = ColorSchemeKeyTokens.PrimaryContainer.value,
contentPadding: PaddingValues = FloatingToolbarDefaults.ContentPadding,
scrollBehavior: FloatingToolbarScrollBehavior? = null,
shape: Shape = FloatingToolbarDefaults.ContainerShape,
leadingContent: @Composable (ColumnScope.() -> Unit)? = null,
trailingContent: @Composable (ColumnScope.() -> Unit)? = null,
content: @Composable ColumnScope.() -> Unit
)
Parameters
name | description |
---|---|
expanded | whether the FloatingToolbar is in expanded mode, i.e. showing [leadingContent] and [trailingContent]. |
modifier | the [Modifier] to be applied to this FloatingToolbar. |
containerColor | the color used for the background of this FloatingToolbar. Use Color.Transparent] to have no color. |
contentPadding | the padding applied to the content of this FloatingToolbar. |
scrollBehavior | a [FloatingToolbarScrollBehavior]. If null, this FloatingToolbar will not automatically react to scrolling. |
shape | the shape used for this FloatingToolbar. |
leadingContent | the leading content of this FloatingToolbar. The default layout here is a [Column], so content inside will be placed vertically. Only showing if [expanded] is true. |
trailingContent | the trailing content of this FloatingToolbar. The default layout here is a [Column], so content inside will be placed vertically. Only showing if [expanded] is true. |
content | the main content of this FloatingToolbar. The default layout here is a [Column], so content inside will be placed vertically. |
@ExperimentalMaterial3ExpressiveApi
@Composable
fun VerticalFloatingToolbar(
expanded: Boolean,
floatingActionButton: @Composable () -> Unit,
modifier: Modifier = Modifier,
colors: FloatingToolbarColors = FloatingToolbarDefaults.standardFloatingToolbarColors(),
contentPadding: PaddingValues = FloatingToolbarDefaults.ContentPadding,
scrollBehavior: FloatingToolbarScrollBehavior? = null,
shape: Shape = FloatingToolbarDefaults.ContainerShape,
floatingActionButtonPosition: FloatingToolbarVerticalFabPosition =
FloatingToolbarVerticalFabPosition.Bottom,
animationSpec: FiniteAnimationSpec<Float> = FloatingToolbarDefaults.animationSpec(),
content: @Composable ColumnScope.() -> Unit
)
Parameters
name | description |
---|---|
expanded | whether the floating toolbar is expanded or not. In its expanded state, the FAB and the toolbar content are organized vertically. Otherwise, only the FAB is visible. |
floatingActionButton | 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]. |
modifier | the [Modifier] to be applied to this floating toolbar. |
colors | 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 | the padding applied to the content of this floating toolbar. |
scrollBehavior | a [FloatingToolbarScrollBehavior]. If provided, this FloatingToolbar will automatically react to scrolling. If your toolbar is positioned along a center edge of the screen (like left or right 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. |
shape | the shape used for this floating toolbar content. |
floatingActionButtonPosition | the position of the floating toolbar's floating action button. By default, the FAB is placed at the bottom of the toolbar (i.e. aligned to the bottom). |
animationSpec | the animation spec to use for this floating toolbar expand and collapse animation. |
content | the main content of this floating toolbar. The default layout here is a [Column], so content inside will be placed vertically. |
Code Examples
ExpandableVerticalFloatingToolbarSample
@OptIn(ExperimentalMaterial3ExpressiveApi::class)
@Preview
@Composable
fun ExpandableVerticalFloatingToolbarSample() {
val context = LocalContext.current
val isTouchExplorationEnabled = remember {
val am = context.getSystemService(Context.ACCESSIBILITY_SERVICE) as AccessibilityManager
am.isEnabled && am.isTouchExplorationEnabled
}
val listState = rememberLazyListState()
var currentItem = 0
val expanded by remember {
derivedStateOf {
val temp = currentItem
currentItem = listState.firstVisibleItemIndex
listState.firstVisibleItemIndex {'<='} temp // true if the list is scrolled up
}
}
Scaffold(
content = { innerPadding ->
Box(Modifier.padding(innerPadding)) {
LazyColumn(
state = listState,
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)
)
}
}
VerticalFloatingToolbar(
modifier = Modifier.align(Alignment.CenterEnd).offset(x = -ScreenOffset),
expanded = expanded || isTouchExplorationEnabled,
leadingContent = { leadingContent() },
trailingContent = { trailingContent() },
content = {
FilledIconButton(
modifier = Modifier.height(64.dp),
onClick = { /* doSomething() */ }
) {
Icon(Icons.Filled.Add, contentDescription = "Localized description")
}
},
)
}
}
)
}
ScrollableVerticalFloatingToolbarSample
@OptIn(ExperimentalMaterial3ExpressiveApi::class)
@Preview
@Composable
fun ScrollableVerticalFloatingToolbarSample() {
val context = LocalContext.current
val isTouchExplorationEnabled = remember {
val am = context.getSystemService(Context.ACCESSIBILITY_SERVICE) as AccessibilityManager
am.isEnabled && am.isTouchExplorationEnabled
}
val listState = rememberLazyListState()
val exitAlwaysScrollBehavior =
FloatingToolbarDefaults.exitAlwaysScrollBehavior(exitDirection = End)
Scaffold(
modifier = Modifier.nestedScroll(exitAlwaysScrollBehavior),
content = { innerPadding ->
Box(Modifier.padding(innerPadding)) {
LazyColumn(
state = listState,
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)
)
}
}
VerticalFloatingToolbar(
modifier = Modifier.align(Alignment.CenterEnd).offset(x = -ScreenOffset),
expanded = true,
leadingContent = { leadingContent() },
trailingContent = { trailingContent() },
content = {
FilledIconButton(
modifier = Modifier.height(64.dp),
onClick = { /* doSomething() */ }
) {
Icon(Icons.Filled.Add, contentDescription = "Localized description")
}
},
scrollBehavior =
if (!isTouchExplorationEnabled) exitAlwaysScrollBehavior else null,
)
}
}
)
}
VerticalFloatingToolbarWithFabSample
@OptIn(ExperimentalMaterial3ExpressiveApi::class)
@Preview
@Composable
fun VerticalFloatingToolbarWithFabSample() {
val context = LocalContext.current
val isTouchExplorationEnabled = remember {
val am = context.getSystemService(Context.ACCESSIBILITY_SERVICE) as AccessibilityManager
am.isEnabled && am.isTouchExplorationEnabled
}
var expanded by rememberSaveable { mutableStateOf(true) }
val vibrantColors = FloatingToolbarDefaults.vibrantFloatingToolbarColors()
Scaffold { 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 VerticalFloatingToolbar. We don't intercept scrolls
// if the touch exploration is enabled (i.e. Talkback).
.then(
if (!isTouchExplorationEnabled) {
Modifier.floatingToolbarVerticalNestedScroll(
expanded = expanded,
onExpand = { expanded = true },
onCollapse = { expanded = false }
)
} else {
Modifier
}
)
.verticalScroll(rememberScrollState())
) {
Text(text = remember { LoremIpsum().values.first() })
}
VerticalFloatingToolbar(
expanded = expanded,
floatingActionButton = {
// Match the FAB to the vibrantColors. See also StandardFloatingActionButton.
FloatingToolbarDefaults.VibrantFloatingActionButton(
onClick = { /* doSomething() */ },
) {
Icon(Icons.Filled.Add, "Localized description")
}
},
modifier =
Modifier.align(Alignment.BottomEnd)
.offset(x = -ScreenOffset, y = -ScreenOffset),
colors = vibrantColors,
content = {
IconButton(onClick = { /* doSomething() */ }) {
Icon(Icons.Filled.Person, contentDescription = "Localized description")
}
IconButton(onClick = { /* doSomething() */ }) {
Icon(Icons.Filled.Edit, contentDescription = "Localized description")
}
IconButton(onClick = { /* doSomething() */ }) {
Icon(Icons.Filled.Favorite, contentDescription = "Localized description")
}
IconButton(onClick = { /* doSomething() */ }) {
Icon(Icons.Filled.MoreVert, contentDescription = "Localized description")
}
},
)
}
}
}
CenteredVerticalFloatingToolbarWithFabSample
@OptIn(ExperimentalMaterial3ExpressiveApi::class)
@Preview
@Composable
fun CenteredVerticalFloatingToolbarWithFabSample() {
val context = LocalContext.current
val isTouchExplorationEnabled = remember {
val am = context.getSystemService(Context.ACCESSIBILITY_SERVICE) as AccessibilityManager
am.isEnabled && am.isTouchExplorationEnabled
}
val exitAlwaysScrollBehavior =
FloatingToolbarDefaults.exitAlwaysScrollBehavior(exitDirection = End)
val vibrantColors = FloatingToolbarDefaults.vibrantFloatingToolbarColors()
Scaffold(modifier = Modifier.nestedScroll(exitAlwaysScrollBehavior)) { innerPadding ->
Box(Modifier.padding(innerPadding)) {
Column(
Modifier.fillMaxWidth()
.padding(horizontal = 16.dp)
.verticalScroll(rememberScrollState())
) {
Text(text = remember { LoremIpsum().values.first() })
}
VerticalFloatingToolbar(
// Always expanded as the toolbar is right-centered. We will use a
// FloatingToolbarScrollBehavior to hide both the toolbar and its FAB on scroll.
expanded = true,
floatingActionButton = {
// Match the FAB to the vibrantColors. See also StandardFloatingActionButton.
FloatingToolbarDefaults.VibrantFloatingActionButton(
onClick = { /* doSomething() */ },
) {
Icon(Icons.Filled.Add, "Localized description")
}
},
modifier = Modifier.align(Alignment.CenterEnd).offset(x = -ScreenOffset),
colors = vibrantColors,
scrollBehavior = if (!isTouchExplorationEnabled) exitAlwaysScrollBehavior else null,
content = {
IconButton(onClick = { /* doSomething() */ }) {
Icon(Icons.Filled.Person, contentDescription = "Localized description")
}
IconButton(onClick = { /* doSomething() */ }) {
Icon(Icons.Filled.Edit, contentDescription = "Localized description")
}
IconButton(onClick = { /* doSomething() */ }) {
Icon(Icons.Filled.Favorite, contentDescription = "Localized description")
}
IconButton(onClick = { /* doSomething() */ }) {
Icon(Icons.Filled.MoreVert, contentDescription = "Localized description")
}
},
)
}
}
}