I'm trying to create a Material 3 Floating Action Button in Jetpack Compose that expands into a Sheet with multiple options on click. I'm trying to achieve something like this:
The above example is from the Material 3 website. However, I haven't got any idea on how to implement such a thing. I tried searching for it online but almost all of the tutorials show transforming a FAB into multiple other FABs on click.
I tried modifying an ExtendedFloatingActionButton
but didn't get the results I wanted. I also tried using AnimatedContent
to animate between a normal FloatingActionButton
and a Column
with multiple Row
s containing other options but still couldn't get the required results.
Any guidance would be appreciated. Thanks in advance!
I got it to be nearly identical, you dont need everything here, some of the parameters were specific to fit in my code. Expandable basically just enables that the fab can be used on multiple different screens, allowing you to choose whether or not it expands. You can get rid of that if you want, same with the other parameters.
// Custom fab that allows for displaying extended content
@Composable
fun CustomFloatingActionButton(
expandable: Boolean,
onFabClick: () -> Unit,
fabIcon: ImageVector
) {
var isExpanded by remember { mutableStateOf(false) }
if (!expandable) { // Close the expanded fab if you change to non expandable nav destination
isExpanded = false
}
val fabSize = 64.dp
val expandedFabWidth by animateDpAsState(
targetValue = if (isExpanded) 200.dp else fabSize,
animationSpec = spring(dampingRatio = 3f)
)
val expandedFabHeight by animateDpAsState(
targetValue = if (isExpanded) 58.dp else fabSize,
animationSpec = spring(dampingRatio = 3f)
)
Column {
// ExpandedBox over the FAB
Box(
modifier = Modifier
.offset(y = (25).dp)
.size(
width = expandedFabWidth,
height = (animateDpAsState(if (isExpanded) 225.dp else 0.dp, animationSpec = spring(dampingRatio = 4f))).value)
.background(
MaterialTheme.colorScheme.surfaceContainer,
shape = RoundedCornerShape(18.dp)
)
) {
// Customize the content of the expanded box as needed
}
FloatingActionButton(
onClick = {
onFabClick()
if (expandable) {
isExpanded = !isExpanded
}
},
modifier = Modifier
.width(expandedFabWidth)
.height(expandedFabHeight),
shape = RoundedCornerShape(18.dp)
) {
Icon(
imageVector = fabIcon,
contentDescription = null,
modifier = Modifier
.size(24.dp)
.offset(x = animateDpAsState(if (isExpanded) -70.dp else 0.dp, animationSpec = spring(dampingRatio = 3f)).value)
)
Text(
text = "Create Reminder",
softWrap = false,
modifier = Modifier
.offset(x = animateDpAsState(if (isExpanded) 10.dp else 50.dp, animationSpec = spring(dampingRatio = 3f)).value)
.alpha(
animateFloatAsState(
targetValue = if (isExpanded) 1f else 0f,
animationSpec = tween(
durationMillis = if (isExpanded) 350 else 100,
delayMillis = if (isExpanded) 100 else 0,
easing = EaseIn)).value)
)
}
}
}