A Floating Action Button (FAB) in Jetpack Compose is a circular button that floats above the UI, typically used to promote a primary action in your application. The Jetpack Compose FloatingActionButton
composable provides a modern implementation of Material Design's FAB component, offering developers a declarative way to add these prominent interactive elements to their Android applications.
Floating Action Buttons in Jetpack Compose represent the main action of a screen and are designed to be visually distinct from other UI elements. They are particularly useful for actions like creating new content, sharing, navigating, or any other primary action that deserves prominence in your app's interface.
Let's start with the fundamental implementation of a Floating Action Button in Jetpack Compose:
import androidx.compose.material.FloatingActionButton
import androidx.compose.material.Icon
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
@Composable
fun BasicFloatingActionButton() {
FloatingActionButton(
onClick = { /* Handle FAB click here */ }
) {
Icon(
imageVector = Icons.Default.Add,
contentDescription = "Add"
)
}
}
This basic implementation creates a standard Floating Action Button with the default Material Design appearance and an "Add" icon. When a user clicks on this Jetpack Compose Floating Action Button, the lambda function provided to the onClick
parameter will be executed.
The Jetpack Compose FloatingActionButton
composable comes with several key properties that allow for extensive customization:
The onClick
property is a required parameter for Floating Action Buttons in Jetpack Compose. It defines the action that will be executed when the FAB is clicked:
FloatingActionButton(
onClick = {
// Your action logic here
viewModel.createNewItem()
}
) {
// Content
}
The modifier
property allows you to apply Jetpack Compose modifiers to customize the layout and appearance of your Floating Action Button:
FloatingActionButton(
modifier = Modifier
.size(72.dp)
.padding(16.dp),
onClick = { /* Action */ }
) {
// Content
}
The backgroundColor
property lets you customize the background color of your Jetpack Compose Floating Action Button:
FloatingActionButton(
onClick = { /* Action */ },
backgroundColor = MaterialTheme.colors.secondary
) {
// Content
}
The contentColor
property controls the color of the content (usually an icon) inside your Floating Action Button:
FloatingActionButton(
onClick = { /* Action */ },
contentColor = Color.White
) {
// Content
}
The elevation
property allows you to customize the elevation (shadow) of your Jetpack Compose Floating Action Button, which affects its visual prominence:
FloatingActionButton(
onClick = { /* Action */ },
elevation = FloatingActionButtonDefaults.elevation(
defaultElevation = 6.dp,
pressedElevation = 12.dp
)
) {
// Content
}
Jetpack Compose also offers an extended version of the Floating Action Button, which includes both an icon and text. This is particularly useful when you want to make the action more explicit:
import androidx.compose.material.ExtendedFloatingActionButton
import androidx.compose.material.Text
@Composable
fun ExtendedFABSample() {
ExtendedFloatingActionButton(
text = { Text("Create") },
icon = { Icon(Icons.Filled.Add, "Add Icon") },
onClick = { /* Handle extended FAB click */ }
)
}
The Jetpack Compose ExtendedFloatingActionButton
shares many properties with the standard FAB but adds specific properties for handling the text and icon layout.
Jetpack Compose Floating Action Buttons come in different sizes to suit various use cases:
This is the standard size for a Floating Action Button in Jetpack Compose, suitable for most primary actions:
FloatingActionButton(
onClick = { /* Action */ }
) {
Icon(Icons.Filled.Add, contentDescription = "Add")
}
Jetpack Compose provides a smaller version for less prominent actions or space-constrained UIs:
SmallFloatingActionButton(
onClick = { /* Action */ }
) {
Icon(Icons.Filled.Add, contentDescription = "Add")
}
With Material 3 in Jetpack Compose, you can also use a larger FAB for even more prominence:
LargeFloatingActionButton(
onClick = { /* Action */ }
) {
Icon(Icons.Filled.Add, contentDescription = "Add")
}
Animations can significantly enhance the user experience when interacting with Floating Action Buttons in Jetpack Compose:
You can animate the appearance and disappearance of a Floating Action Button:
var visible by remember { mutableStateOf(true) }
AnimatedVisibility(
visible = visible,
enter = fadeIn() + scaleIn(),
exit = fadeOut() + scaleOut()
) {
FloatingActionButton(
onClick = { visible = !visible }
) {
Icon(Icons.Filled.Add, contentDescription = "Add")
}
}
You can animate the rotation of the icon inside a Floating Action Button to indicate state changes:
var expanded by remember { mutableStateOf(false) }
val rotationState by animateFloatAsState(
targetValue = if (expanded) 45f else 0f,
label = "FAB rotation"
)
FloatingActionButton(
onClick = { expanded = !expanded }
) {
Icon(
Icons.Filled.Add,
contentDescription = "Add",
modifier = Modifier.rotate(rotationState)
)
}
In most applications, you'll want to integrate your Floating Action Button with the Scaffold component, which provides a proper placement according to Material Design guidelines:
Scaffold(
floatingActionButton = {
FloatingActionButton(
onClick = { /* Action */ }
) {
Icon(Icons.Filled.Add, contentDescription = "Add")
}
},
floatingActionButtonPosition = FabPosition.End,
isFloatingActionButtonDocked = true
) { paddingValues ->
// Your screen content here
Box(modifier = Modifier.padding(paddingValues)) {
// Content
}
}
The floatingActionButtonPosition
parameter determines where the FAB appears on the screen. Common options include:
FabPosition.End
: Places the FAB at the bottom-end corner (default)FabPosition.Center
: Places the FAB centered at the bottomThe isFloatingActionButtonDocked
parameter determines whether the FAB should be docked with the bottom app bar (if present).
A common pattern is to implement a speed dial or expandable FAB that reveals multiple actions when clicked:
@Composable
fun SpeedDialFAB() {
var expanded by remember { mutableStateOf(false) }
Column(
horizontalAlignment = Alignment.End
) {
if (expanded) {
SmallFloatingActionButton(
onClick = { /* Handle action 1 */ },
modifier = Modifier.padding(vertical = 8.dp)
) {
Icon(Icons.Filled.Edit, contentDescription = "Edit")
}
SmallFloatingActionButton(
onClick = { /* Handle action 2 */ },
modifier = Modifier.padding(vertical = 8.dp)
) {
Icon(Icons.Filled.Share, contentDescription = "Share")
}
}
FloatingActionButton(
onClick = { expanded = !expanded }
) {
Icon(
imageVector = if (expanded) Icons.Filled.Close else Icons.Filled.Add,
contentDescription = if (expanded) "Close" else "Expand"
)
}
}
}
This implementation shows or hides additional, smaller Floating Action Buttons when the main FAB is clicked, creating a convenient menu of related actions.
Here are some common customization patterns for Floating Action Buttons in Jetpack Compose:
You can customize the shape of your Floating Action Button beyond the default circle:
FloatingActionButton(
onClick = { /* Action */ },
shape = RoundedCornerShape(8.dp)
) {
Icon(Icons.Filled.Add, contentDescription = "Add")
}
You can apply a gradient background to your Floating Action Button for a more eye-catching appearance:
FloatingActionButton(
onClick = { /* Action */ },
backgroundColor = Color.Transparent,
contentColor = Color.White
) {
Box(
modifier = Modifier
.fillMaxSize()
.background(
brush = Brush.linearGradient(
colors = listOf(Color(0xFF9C27B0), Color(0xFF673AB7)),
start = Offset(0f, 0f),
end = Offset(100f, 100f)
),
shape = CircleShape
)
) {
Icon(
Icons.Filled.Add,
contentDescription = "Add",
modifier = Modifier.align(Alignment.Center)
)
}
}
You can add a badge to your Floating Action Button to indicate unread notifications or pending actions:
Box {
FloatingActionButton(
onClick = { /* Action */ }
) {
Icon(Icons.Filled.Add, contentDescription = "Add")
}
Badge(
modifier = Modifier
.align(Alignment.TopEnd)
.offset((-8).dp, 8.dp)
) {
Text("3")
}
}
Adapting your Floating Action Button for different screen sizes and orientations is crucial for a responsive design:
@Composable
fun ResponsiveFAB() {
val configuration = LocalConfiguration.current
val isLandscape = configuration.orientation == Configuration.ORIENTATION_LANDSCAPE
if (isLandscape) {
// Place FAB in a different position for landscape
Box(
modifier = Modifier.fillMaxSize(),
contentAlignment = Alignment.BottomStart
) {
FloatingActionButton(
onClick = { /* Action */ },
modifier = Modifier.padding(16.dp)
) {
Icon(Icons.Filled.Add, contentDescription = "Add")
}
}
} else {
// Default position for portrait
Box(
modifier = Modifier.fillMaxSize(),
contentAlignment = Alignment.BottomEnd
) {
FloatingActionButton(
onClick = { /* Action */ },
modifier = Modifier.padding(16.dp)
) {
Icon(Icons.Filled.Add, contentDescription = "Add")
}
}
}
}