DropdownMenuItem

Functions summary

Unit
@Composable
DropdownMenuItem(
    text: @Composable () -> Unit,
    onClick: () -> Unit,
    modifier: Modifier,
    leadingIcon: (@Composable () -> Unit)?,
    trailingIcon: (@Composable () -> Unit)?,
    enabled: Boolean,
    colors: MenuItemColors,
    contentPadding: PaddingValues,
    interactionSource: MutableInteractionSource?
)

Material Design dropdown menu

Cmn
android
Unit
@Composable
DropdownMenuItem(
    onClick: () -> Unit,
    text: @Composable () -> Unit,
    shape: Shape,
    modifier: Modifier,
    leadingIcon: (@Composable () -> Unit)?,
    trailingContent: (@Composable () -> Unit)?,
    supportingText: (@Composable () -> Unit)?,
    enabled: Boolean,
    colors: MenuItemColors,
    horizontalArrangement: Arrangement.Horizontal,
    contentPadding: PaddingValues,
    interactionSource: MutableInteractionSource?
)

Material Design dropdown menu

Cmn

Functions

@Composable
fun DropdownMenuItem(
    text: @Composable () -> Unit,
    onClick: () -> Unit,
    modifier: Modifier = Modifier,
    leadingIcon: (@Composable () -> Unit)? = null,
    trailingIcon: (@Composable () -> Unit)? = null,
    enabled: Boolean = true,
    colors: MenuItemColors = MenuDefaults.itemColors(),
    contentPadding: PaddingValues = MenuDefaults.DropdownMenuItemContentPadding,
    interactionSource: MutableInteractionSource? = null
): Unit

Material Design dropdown menu

Menus display a list of choices on a temporary surface. They appear when users interact with a button, action, or other control.

Dropdown menu
image

Example usage:

import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Edit
import androidx.compose.material.icons.filled.MoreVert
import androidx.compose.material.icons.filled.Settings
import androidx.compose.material.icons.outlined.Edit
import androidx.compose.material.icons.outlined.Email
import androidx.compose.material.icons.outlined.MoreVert
import androidx.compose.material.icons.outlined.Settings
import androidx.compose.material3.DropdownMenu
import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.PlainTooltip
import androidx.compose.material3.Text
import androidx.compose.material3.TooltipAnchorPosition
import androidx.compose.material3.TooltipBox
import androidx.compose.material3.TooltipDefaults
import androidx.compose.material3.rememberTooltipState
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.semantics.LiveRegionMode
import androidx.compose.ui.semantics.liveRegion
import androidx.compose.ui.semantics.paneTitle
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.text.style.TextAlign

var expanded by remember { mutableStateOf(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(
                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 = { expanded = true }) {
            Icon(Icons.Default.MoreVert, contentDescription = "Localized description")
        }
    }
    DropdownMenu(expanded = expanded, onDismissRequest = { expanded = false }) {
        DropdownMenuItem(
            text = { Text("Edit") },
            onClick = { /* Handle edit! */ },
            leadingIcon = { Icon(Icons.Outlined.Edit, contentDescription = null) },
        )
        DropdownMenuItem(
            text = { Text("Settings") },
            onClick = { /* Handle settings! */ },
            leadingIcon = { Icon(Icons.Outlined.Settings, contentDescription = null) },
        )
        HorizontalDivider()
        DropdownMenuItem(
            text = { Text("Send Feedback") },
            onClick = { /* Handle send feedback! */ },
            leadingIcon = { Icon(Icons.Outlined.Email, contentDescription = null) },
            trailingIcon = { Text("F11", textAlign = TextAlign.Center) },
        )
    }
}
Parameters
text: @Composable () -> Unit

text of the menu item

onClick: () -> Unit

called when this menu item is clicked

modifier: Modifier = Modifier

the Modifier to be applied to this menu item

leadingIcon: (@Composable () -> Unit)? = null

optional leading icon to be displayed at the beginning of the item's text

trailingIcon: (@Composable () -> Unit)? = null

optional trailing icon to be displayed at the end of the item's text. This trailing icon slot can also accept Text to indicate a keyboard shortcut.

enabled: Boolean = true

controls the enabled state of this menu item. When false, this component will not respond to user input, and it will appear visually disabled and disabled to accessibility services.

colors: MenuItemColors = MenuDefaults.itemColors()

MenuItemColors that will be used to resolve the colors used for this menu item in different states. See MenuDefaults.itemColors.

contentPadding: PaddingValues = MenuDefaults.DropdownMenuItemContentPadding

the padding applied to the content of this menu item

interactionSource: MutableInteractionSource? = null

an optional hoisted MutableInteractionSource for observing and emitting Interactions for this menu item. You can use this to change the menu item's appearance or preview the menu item in different states. Note that if null is provided, interactions will still happen internally.

@Composable
fun DropdownMenuItem(
    onClick: () -> Unit,
    text: @Composable () -> Unit,
    shape: Shape,
    modifier: Modifier = Modifier,
    leadingIcon: (@Composable () -> Unit)? = null,
    trailingContent: (@Composable () -> Unit)? = null,
    supportingText: (@Composable () -> Unit)? = null,
    enabled: Boolean = true,
    colors: MenuItemColors = MenuDefaults.itemColors(),
    horizontalArrangement: Arrangement.Horizontal = MenuDefaults.DropdownMenuItemHorizontalArrangement,
    contentPadding: PaddingValues = MenuDefaults.DropdownMenuSelectableItemContentPadding,
    interactionSource: MutableInteractionSource? = null
): Unit

Material Design dropdown menu

Menus display a list of choices on a temporary surface. They appear when users interact with a button, action, or other control.

Dropdown menu
image

Example usage:

import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Check
import androidx.compose.material.icons.filled.Edit
import androidx.compose.material.icons.filled.Home
import androidx.compose.material.icons.filled.Info
import androidx.compose.material.icons.filled.MoreVert
import androidx.compose.material.icons.filled.Settings
import androidx.compose.material.icons.outlined.Edit
import androidx.compose.material.icons.outlined.Home
import androidx.compose.material.icons.outlined.Info
import androidx.compose.material.icons.outlined.MoreVert
import androidx.compose.material.icons.outlined.Settings
import androidx.compose.material3.ButtonGroup
import androidx.compose.material3.CheckableDropdownMenuItem
import androidx.compose.material3.DropdownMenu
import androidx.compose.material3.DropdownMenuGroup
import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.DropdownMenuPopup
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MenuDefaults
import androidx.compose.material3.PlainTooltip
import androidx.compose.material3.Text
import androidx.compose.material3.TooltipAnchorPosition
import androidx.compose.material3.TooltipBox
import androidx.compose.material3.TooltipDefaults
import androidx.compose.material3.rememberTooltipState
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.semantics.LiveRegionMode
import androidx.compose.ui.semantics.liveRegion
import androidx.compose.ui.semantics.paneTitle
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.util.fastForEachIndexed

val groupInteractionSource = remember { MutableInteractionSource() }
var expanded 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(Icons.Outlined.Home, Icons.Outlined.MoreVert))
val groupItemCheckedTrailingIcons: List<List<ImageVector?>> =
    listOf(listOf(null, null), listOf(Icons.Filled.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(
                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 = { 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.DropdownMenuGroupLabel { Text(label) }
                HorizontalDivider(
                    modifier = Modifier.padding(MenuDefaults.HorizontalDividerPadding)
                )
                val groupItemCount = groupItemLabels[groupIndex].size
                groupItemLabels[groupIndex].fastForEachIndexed { itemIndex, itemLabel ->
                    CheckableDropdownMenuItem(
                        text = { Text(itemLabel) },
                        supportingText =
                            groupItemSupportingText[groupIndex][itemIndex]?.let { supportingText
                                ->
                                { Text(supportingText) }
                            },
                        shapes = MenuDefaults.itemShape(itemIndex, groupItemCount),
                        leadingIcon =
                            groupItemLeadingIcons[groupIndex][itemIndex]?.let { iconData ->
                                {
                                    Icon(
                                        iconData,
                                        modifier = Modifier.size(MenuDefaults.LeadingIconSize),
                                        contentDescription = null,
                                    )
                                }
                            },
                        checkedLeadingIcon = {
                            Icon(
                                groupItemCheckedLeadingIcons[groupIndex][itemIndex],
                                modifier = Modifier.size(MenuDefaults.LeadingIconSize),
                                contentDescription = null,
                            )
                        },
                        trailingContent =
                            if (checked[groupIndex][itemIndex]) {
                                groupItemCheckedTrailingIcons[groupIndex][itemIndex]?.let {
                                    iconData ->
                                    {
                                        Icon(
                                            iconData,
                                            modifier =
                                                Modifier.size(MenuDefaults.TrailingIconSize),
                                            contentDescription = null,
                                        )
                                    }
                                }
                            } else {
                                groupItemTrailingIcons[groupIndex][itemIndex]?.let { iconData ->
                                    {
                                        Icon(
                                            iconData,
                                            modifier =
                                                Modifier.size(MenuDefaults.TrailingIconSize),
                                            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()
        }
    }
}
Parameters
onClick: () -> Unit

called when this menu item is clicked

text: @Composable () -> Unit

text of the menu item.

shape: Shape

Shape of this menu item. The shapes provided should be determined by the number of items in the group or menu as well as the item's position in the menu. Please use MenuDefaults.leadingItemShape for the first item in a list, MenuDefaults.middleItemShape for the middle items in a list, and MenuDefaults.trailingItemShape for the last item in a list.

modifier: Modifier = Modifier

the Modifier to be applied to this menu item.

leadingIcon: (@Composable () -> Unit)? = null

optional leading icon to be displayed when the item is unchecked.

trailingContent: (@Composable () -> Unit)? = null

optional trailing content to be displayed at the end of the item's text.

supportingText: (@Composable () -> Unit)? = null

optional supporting text of the menu item.

enabled: Boolean = true

controls the enabled state of this menu item. When false, this component will not respond to user input.

colors: MenuItemColors = MenuDefaults.itemColors()

MenuItemColors that will be used to resolve the colors for this menu item. Please see MenuDefaults.itemColors.

horizontalArrangement: Arrangement.Horizontal = MenuDefaults.DropdownMenuItemHorizontalArrangement

the horizontal arrangement of the menu item's children.

contentPadding: PaddingValues = MenuDefaults.DropdownMenuSelectableItemContentPadding

the padding applied to the content of this menu item.

interactionSource: MutableInteractionSource? = null

an optional hoisted MutableInteractionSource for observing and emitting Interactions for this menu item.