@OptIn(ExperimentalMaterial3ExpressiveApi::class, ExperimentalMaterial3Api::class)
@Preview
@Composable
fun CenteredVerticalFloatingToolbarWithFabSample() {
val exitAlwaysScrollBehavior =
FloatingToolbarDefaults.exitAlwaysScrollBehavior(exitDirection = End)
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.
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 = {
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.CenterEnd).offset(x = -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")
}
}
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() })
}
}
}
}
@OptIn(ExperimentalMaterial3ExpressiveApi::class, ExperimentalMaterial3Api::class)
@Preview
@Composable
fun ExpandableVerticalFloatingToolbarSample() {
var expanded by rememberSaveable { mutableStateOf(true) }
Scaffold(
content = { 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.
VerticalFloatingToolbar(
modifier =
Modifier.align(Alignment.CenterEnd).offset(x = -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.height(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),
)
}
}
}
}
)
}
@OptIn(ExperimentalMaterial3ExpressiveApi::class, ExperimentalMaterial3Api::class)
@Preview
@Composable
fun OverflowingVerticalFloatingToolbarSample() {
Scaffold(
content = { 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.
VerticalFloatingToolbar(
modifier =
Modifier.align(Alignment.CenterEnd).offset(x = -ScreenOffset).zIndex(1f),
expanded = true,
leadingContent = { LeadingContent() },
trailingContent = {
AppBarColumn {
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.height(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),
)
}
}
}
}
)
}
@OptIn(ExperimentalMaterial3ExpressiveApi::class, ExperimentalMaterial3Api::class)
@Preview
@Composable
fun ScrollableVerticalFloatingToolbarSample() {
val exitAlwaysScrollBehavior =
FloatingToolbarDefaults.exitAlwaysScrollBehavior(exitDirection = End)
Scaffold(
modifier = Modifier.nestedScroll(exitAlwaysScrollBehavior),
content = { 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.
VerticalFloatingToolbar(
modifier =
Modifier.align(Alignment.CenterEnd).offset(x = -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.height(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),
)
}
}
}
},
)
}
@OptIn(ExperimentalMaterial3ExpressiveApi::class, ExperimentalMaterial3Api::class)
@Preview
@Composable
fun VerticalFloatingToolbarWithFabSample() {
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.
VerticalFloatingToolbar(
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 VerticalFloatingToolbar.
.then(
Modifier.floatingToolbarVerticalNestedScroll(
expanded = expanded,
onExpand = { expanded = true },
onCollapse = { expanded = false },
)
)
.verticalScroll(rememberScrollState())
) {
Text(text = remember { LoremIpsum().values.first() })
}
}
}
}