HorizontalFloatingToolbarWithFabSample
@OptIn(ExperimentalMaterial3Api::class)
@Preview
@Sampled
@Composable
fun HorizontalFloatingToolbarWithFabSample() {
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(
modifier =
Modifier.semantics {
// TODO(b/496338253): Remove this modifier once bug where
// tooltip text is not announced by a11y screen readers is
// resolved.
liveRegion = LiveRegionMode.Assertive
paneTitle = "Localized description"
}
) {
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(
modifier =
Modifier.semantics {
// TODO(b/496338253): Remove this modifier once bug where
// tooltip text is not announced by a11y screen readers is
// resolved.
liveRegion = LiveRegionMode.Assertive
paneTitle = "Localized description"
}
) {
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(
modifier =
Modifier.semantics {
// TODO(b/496338253): Remove this modifier once bug where
// tooltip text is not announced by a11y screen readers is
// resolved.
liveRegion = LiveRegionMode.Assertive
paneTitle = "Localized description"
}
) {
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(
modifier =
Modifier.semantics {
// TODO(b/496338253): Remove this modifier once bug where
// tooltip text is not announced by a11y screen readers is
// resolved.
liveRegion = LiveRegionMode.Assertive
paneTitle = "Localized description"
}
) {
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(
modifier =
Modifier.semantics {
// TODO(b/496338253): Remove this modifier once bug where
// tooltip text is not announced by a11y screen readers is
// resolved.
liveRegion = LiveRegionMode.Assertive
paneTitle = "Localized description"
}
) {
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() })
}
}
}
}
CenteredHorizontalFloatingToolbarWithFabSample
@OptIn(ExperimentalMaterial3Api::class)
@Preview
@Sampled
@Composable
fun CenteredHorizontalFloatingToolbarWithFabSample() {
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(
modifier =
Modifier.semantics {
// TODO(b/496338253): Remove this modifier once bug where
// tooltip text is not announced by a11y screen readers is
// resolved.
liveRegion = LiveRegionMode.Assertive
paneTitle = "Localized description"
}
) {
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(
modifier =
Modifier.semantics {
// TODO(b/496338253): Remove this modifier once bug where
// tooltip text is not announced by a11y screen readers is
// resolved.
liveRegion = LiveRegionMode.Assertive
paneTitle = "Localized description"
}
) {
Text("Localized description")
}
},
state = rememberTooltipState(),
) {
IconButton(onClick = { /* doSomething() */ }) {
Icon(Icons.Filled.Person, contentDescription = "Localized description")
}
}
TooltipBox(
positionProvider =
TooltipDefaults.rememberTooltipPositionProvider(
TooltipAnchorPosition.Above
),
tooltip = {
PlainTooltip(
modifier =
Modifier.semantics {
// TODO(b/496338253): Remove this modifier once bug where
// tooltip text is not announced by a11y screen readers is
// resolved.
liveRegion = LiveRegionMode.Assertive
paneTitle = "Localized description"
}
) {
Text("Localized description")
}
},
state = rememberTooltipState(),
) {
IconButton(onClick = { /* doSomething() */ }) {
Icon(Icons.Filled.Edit, contentDescription = "Localized description")
}
}
TooltipBox(
positionProvider =
TooltipDefaults.rememberTooltipPositionProvider(
TooltipAnchorPosition.Above
),
tooltip = {
PlainTooltip(
modifier =
Modifier.semantics {
// TODO(b/496338253): Remove this modifier once bug where
// tooltip text is not announced by a11y screen readers is
// resolved.
liveRegion = LiveRegionMode.Assertive
paneTitle = "Localized description"
}
) {
Text("Localized description")
}
},
state = rememberTooltipState(),
) {
IconButton(onClick = { /* doSomething() */ }) {
Icon(
Icons.Filled.Favorite,
contentDescription = "Localized description",
)
}
}
TooltipBox(
positionProvider =
TooltipDefaults.rememberTooltipPositionProvider(
TooltipAnchorPosition.Above
),
tooltip = {
PlainTooltip(
modifier =
Modifier.semantics {
// TODO(b/496338253): Remove this modifier once bug where
// tooltip text is not announced by a11y screen readers is
// resolved.
liveRegion = LiveRegionMode.Assertive
paneTitle = "Localized description"
}
) {
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() })
}
}
}
}
HorizontalFloatingToolbarAsScaffoldFabSample
@OptIn(ExperimentalMaterial3Api::class)
@Preview
@Sampled
@Composable
fun HorizontalFloatingToolbarAsScaffoldFabSample() {
var expanded by rememberSaveable { mutableStateOf(true) }
val vibrantColors = FloatingToolbarDefaults.vibrantFloatingToolbarColors()
Scaffold(
floatingActionButton = {
HorizontalFloatingToolbar(
expanded = expanded,
floatingActionButton = {
TooltipBox(
positionProvider =
TooltipDefaults.rememberTooltipPositionProvider(
TooltipAnchorPosition.Above
),
tooltip = {
PlainTooltip(
modifier =
Modifier.semantics {
// TODO(b/496338253): Remove this modifier once bug where
// tooltip text is not announced by a11y screen readers is
// resolved.
liveRegion = LiveRegionMode.Assertive
paneTitle = "Localized description"
}
) {
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(
modifier =
Modifier.semantics {
// TODO(b/496338253): Remove this modifier once bug where
// tooltip text is not announced by a11y screen readers is
// resolved.
liveRegion = LiveRegionMode.Assertive
paneTitle = "Localized description"
}
) {
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(
modifier =
Modifier.semantics {
// TODO(b/496338253): Remove this modifier once bug where
// tooltip text is not announced by a11y screen readers is
// resolved.
liveRegion = LiveRegionMode.Assertive
paneTitle = "Localized description"
}
) {
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(
modifier =
Modifier.semantics {
// TODO(b/496338253): Remove this modifier once bug where
// tooltip text is not announced by a11y screen readers is
// resolved.
liveRegion = LiveRegionMode.Assertive
paneTitle = "Localized description"
}
) {
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(
modifier =
Modifier.semantics {
// TODO(b/496338253): Remove this modifier once bug where
// tooltip text is not announced by a11y screen readers is
// resolved.
liveRegion = LiveRegionMode.Assertive
paneTitle = "Localized description"
}
) {
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() })
}
}
}
}