DropdownMenuPopup
A `Popup` that provides the foundation for building a custom menu.
DropdownMenuPopup
Composable Component
A Popup that provides the foundation for building a custom menu.
Common
@ExperimentalMaterial3ExpressiveApi
@Composable
expect fun DropdownMenuPopup(
expanded: Boolean,
onDismissRequest: () -> Unit,
modifier: Modifier = Modifier,
offset: DpOffset = DpOffset(0.dp, 0.dp),
properties: PopupProperties = DefaultMenuProperties,
content: @Composable ColumnScope.() -> Unit,
)
Parameters
| expanded | whether the menu is expanded or not. |
| onDismissRequest | called when the user requests to dismiss the menu, such as by tapping outside the menu's bounds. |
| modifier | Modifier to be applied to the menu's content. |
| offset | DpOffset from the original position of the menu. |
| properties | PopupProperties for further customization of this popup's behavior. |
| content | the content of this dropdown menu. |
Android
@ExperimentalMaterial3ExpressiveApi
@Composable
actual fun DropdownMenuPopup(
expanded: Boolean,
onDismissRequest: () -> Unit,
modifier: Modifier,
offset: DpOffset,
properties: PopupProperties,
content: @Composable ColumnScope.() -> Unit,
)
Code Examples
GroupedMenuSample
@OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterial3ExpressiveApi::class)
@Preview
@Composable
fun GroupedMenuSample() {
val groupInteractionSource = remember { MutableInteractionSource() }
var expanded by remember { mutableStateOf(false) }
var homeChecked by remember { mutableStateOf(false) }
val groupLabels = listOf("Modification", "Navigation")
val groupItemLabels = listOf(listOf("Edit", "Settings"), listOf("Home", "More Options"))
val groupItemLeadingIcons =
listOf(
listOf(Icons.Outlined.Edit, Icons.Outlined.Settings),
listOf(null, Icons.Outlined.Info),
)
val groupItemCheckedLeadingIcons =
listOf(
listOf(Icons.Filled.Edit, Icons.Filled.Settings),
listOf(Icons.Filled.Check, Icons.Filled.Info),
)
val groupItemTrailingIcons: List<List<ImageVector?>> =
listOf(
listOf(null, null),
listOf(
if (homeChecked) {
Icons.Filled.Home
} else {
Icons.Outlined.Home
},
Icons.Filled.MoreVert,
),
)
val groupItemSupportingText: List<List<String?>> =
listOf(listOf("Edit mode", null), listOf(null, "Opens menu"))
val checked = remember {
listOf(mutableStateListOf(false, false), mutableStateListOf(false, false))
}
Box(modifier = Modifier.fillMaxSize().wrapContentSize(Alignment.TopStart)) {
// Icon button should have a tooltip associated with it for a11y.
TooltipBox(
positionProvider =
TooltipDefaults.rememberTooltipPositionProvider(TooltipAnchorPosition.Above),
tooltip = { PlainTooltip { Text("Localized description") } },
state = rememberTooltipState(),
) {
IconButton(onClick = { expanded = true }) {
Icon(Icons.Default.MoreVert, contentDescription = "Localized description")
}
}
DropdownMenuPopup(expanded = expanded, onDismissRequest = { expanded = false }) {
val groupCount = groupLabels.size
groupLabels.fastForEachIndexed { groupIndex, label ->
DropdownMenuGroup(
shapes = MenuDefaults.groupShape(groupIndex, groupCount),
interactionSource = groupInteractionSource,
) {
MenuDefaults.Label { Text(label) }
HorizontalDivider(
modifier =
Modifier.padding(horizontal = MenuDefaults.HorizontalDividerPadding)
)
val groupItemCount = groupItemLabels[groupIndex].size
groupItemLabels[groupIndex].fastForEachIndexed { itemIndex, itemLabel ->
DropdownMenuItem(
text = {
val itemSupportingText =
groupItemSupportingText[groupIndex][itemIndex]
if (itemSupportingText != null) {
MenuDefaults.LabelWithSupportingText(
supportingText = { Text(itemSupportingText) }
) {
Text(itemLabel)
}
} else {
Text(itemLabel)
}
},
shapes = MenuDefaults.itemShape(itemIndex, groupItemCount),
leadingIcon =
groupItemLeadingIcons[groupIndex][itemIndex]?.let { iconData ->
{ Icon(iconData, contentDescription = null) }
},
checkedLeadingIcon = {
Icon(
groupItemCheckedLeadingIcons[groupIndex][itemIndex],
contentDescription = null,
)
},
trailingIcon =
groupItemTrailingIcons[groupIndex][itemIndex]?.let { iconData ->
{ Icon(iconData, contentDescription = null) }
},
checked = checked[groupIndex][itemIndex],
onCheckedChange = { checked[groupIndex][itemIndex] = it },
)
}
}
if (groupIndex != groupCount - 1) {
Spacer(Modifier.height(MenuDefaults.GroupSpacing))
}
}
if (checked.last().last()) {
DropdownMenuButtonGroup()
}
}
}
}
Create your own Component Library
Material Components are meant to be used as is and they do not allow customizations. To build your own Jetpack Compose component library use Compose Unstyled