DropdownMenu & Tooltip in Compose: Menus, Selectors & Hints
Jetpack Compose provides powerful components for displaying dropdowns, menus, and contextual information. This guide covers the essential UI patterns: DropdownMenu, ExposedDropdownMenuBox, and tooltip components.
DropdownMenu: Basic Dropdown Lists
The DropdownMenu composable displays a dropdown menu anchored to a button:
var expanded by remember { mutableStateOf(false) }
Box {
Button(onClick = { expanded = true }) {
Text("Menu")
}
DropdownMenu(
expanded = expanded,
onDismissRequest = { expanded = false }
) {
DropdownMenuItem(
text = { Text("Edit") },
onClick = { expanded = false }
)
DropdownMenuItem(
text = { Text("Delete") },
onClick = { expanded = false }
)
}
}
ExposedDropdownMenuBox: Select-Style UI
For form-like dropdown selections, use ExposedDropdownMenuBox:
var selectedOption by remember { mutableStateOf("") }
var expanded by remember { mutableStateOf(false) }
val options = listOf("Option A", "Option B", "Option C")
ExposedDropdownMenuBox(
expanded = expanded,
onExpandedChange = { expanded = !expanded }
) {
TextField(
modifier = Modifier.menuAnchor(),
value = selectedOption,
onValueChange = { selectedOption = it },
label = { Text("Select") },
readOnly = true,
trailingIcon = { ExposedDropdownMenuDefaults.TrailingIcon(expanded) }
)
ExposedDropdownMenu(
expanded = expanded,
onDismissRequest = { expanded = false }
) {
options.forEach { option ->
DropdownMenuItem(
text = { Text(option) },
onClick = {
selectedOption = option
expanded = false
}
)
}
}
}
Tooltips: PlainTooltip & RichTooltip
Display informational hints with tooltips:
// PlainTooltip
PlainTooltip(
tooltip = { Text("Save document") }
) {
Button(onClick = { }) {
Icon(Icons.Default.Save, contentDescription = null)
}
}
// RichTooltip with title
RichTooltip(
title = { Text("Advanced Options") },
action = { Text("Learn more") }
) {
Button(onClick = { }) {
Text("Options")
}
}
Context Menu with combinedClickable
Long-press menus using combinedClickable with onLongClick:
var expanded by remember { mutableStateOf(false) }
var offset by remember { mutableStateOf(DpOffset.Zero) }
Box(
modifier = Modifier
.combinedClickable(
onClick = { },
onLongClick = { expanded = true }
)
.background(Color.LightGray)
.padding(16.dp),
contentAlignment = Alignment.Center
) {
Text("Long press for menu")
DropdownMenu(
expanded = expanded,
onDismissRequest = { expanded = false },
offset = offset
) {
DropdownMenuItem(
text = { Text("Copy") },
onClick = { expanded = false }
)
DropdownMenuItem(
text = { Text("Paste") },
onClick = { expanded = false }
)
}
}
menuAnchor Modifier
Use menuAnchor() to properly position menus relative to their trigger:
var expanded by remember { mutableStateOf(false) }
Box {
Button(
modifier = Modifier.menuAnchor(),
onClick = { expanded = true }
) {
Text("Actions")
}
DropdownMenu(
expanded = expanded,
onDismissRequest = { expanded = false }
) {
// menu items
}
}
Best Practices
- Use
ExposedDropdownMenuBoxfor form selections - Prefer
DropdownMenufor action menus - Add tooltips to complex UI elements for discoverability
- Use
combinedClickablefor context menus - Always provide meaningful
contentDescriptionfor accessibility
8 Android App Templates → https://myougatheax.gumroad.com
Top comments (0)