New Compose Multiplatform components arrived on Composables UICheck it out →

Component in Material 3 Compose

DropdownMenu

Common
Android

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

Last updated:

Installation

dependencies {
   implementation("androidx.compose.material3:material3:1.3.0-beta04")
}

Overloads

@Composable
fun DropdownMenu(
    expanded: Boolean,
    onDismissRequest: () -> Unit,
    modifier: Modifier = Modifier,
    offset: DpOffset = DpOffset(0.dp, 0.dp),
    scrollState: ScrollState = rememberScrollState(),
    properties: PopupProperties = DefaultMenuProperties,
    shape: Shape = MenuDefaults.shape,
    containerColor: Color = MenuDefaults.containerColor,
    tonalElevation: Dp = MenuDefaults.TonalElevation,
    shadowElevation: Dp = MenuDefaults.ShadowElevation,
    border: BorderStroke? = null,
    content: @Composable ColumnScope.() -> Unit
)

Parameters

namedescription
expandedwhether the menu is expanded or not
onDismissRequestcalled 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. The offset respects the [LayoutDirection], so the offset's x position will be added in LTR and subtracted in RTL.
scrollStatea [ScrollState] to used by the menu's content for items vertical scrolling
properties[PopupProperties] for further customization of this popup's behavior
shapethe shape of the menu
containerColorthe container color of the menu
tonalElevationwhen [containerColor] is [ColorScheme.surface], a translucent primary color overlay is applied on top of the container. A higher tonal elevation value will result in a darker color in light theme and lighter color in dark theme. See also: [Surface].
shadowElevationthe elevation for the shadow below the menu
borderthe border to draw around the container of the menu. Pass null for no border.
contentthe content of this dropdown menu, typically a [DropdownMenuItem]
@Composable
@Deprecated(
    level = DeprecationLevel.HIDDEN,
    replaceWith =
        ReplaceWith(
            expression =
                "DropdownMenu(expanded,onDismissRequest, modifier, offset, " +
                    "rememberScrollState(), properties, content)",
            "androidx.compose.foundation.rememberScrollState"
        ),
    message = "Replaced by a DropdownMenu function with a ScrollState parameter"

@OptIn(ExperimentalMaterial3Api::class
@Suppress("ModifierParameter"
fun DropdownMenu(
    expanded: Boolean,
    onDismissRequest: () -> Unit,
    modifier: Modifier,
    offset: DpOffset,
    properties: PopupProperties,
    content: @Composable ColumnScope.() -> Unit
)
@Composable
@Deprecated(
    level = DeprecationLevel.HIDDEN,
    replaceWith =
        ReplaceWith(
            expression =
                "DropdownMenu(\n" +
                    "    expanded = expanded,\n" +
                    "    onDismissRequest = onDismissRequest,\n" +
                    "    modifier = modifier,\n" +
                    "    offset = offset,\n" +
                    "    scrollState = scrollState,\n" +
                    "    properties = properties,\n" +
                    "    shape = MenuDefaults.shape,\n" +
                    "    containerColor = MenuDefaults.containerColor,\n" +
                    "    tonalElevation = MenuDefaults.TonalElevation,\n" +
                    "    shadowElevation = MenuDefaults.ShadowElevation,\n" +
                    "    border = null,\n" +
                    "    content = content,\n" +
                    ")",
        ),
    message =
        "Maintained for binary compatibility. Use overload with parameters for shape, " +
            "color, elevation, and border."

fun DropdownMenu(
    expanded: Boolean,
    onDismissRequest: () -> Unit,
    modifier: Modifier = Modifier,
    offset: DpOffset = DpOffset(0.dp, 0.dp),
    scrollState: ScrollState = rememberScrollState(),
    properties: PopupProperties = PopupProperties(focusable = true),
    content: @Composable ColumnScope.() -> Unit
)
@Composable
fun DropdownMenu(
    expanded: Boolean,
    onDismissRequest: () -> Unit,
    modifier: Modifier,
    offset: DpOffset,
    scrollState: ScrollState,
    properties: PopupProperties,
    shape: Shape,
    containerColor: Color,
    tonalElevation: Dp,
    shadowElevation: Dp,
    border: BorderStroke?,
    content: @Composable ColumnScope.() -> Unit
)
@Composable
@Deprecated("Maintained for binary compatibility", level = DeprecationLevel.HIDDEN
fun DropdownMenu(
    expanded: Boolean,
    onDismissRequest: () -> Unit,
    modifier: Modifier = Modifier,
    offset: DpOffset = DpOffset(0.dp, 0.dp),
    content: @Composable ColumnScope.() -> Unit
)
@Composable
@Suppress("ModifierParameter"
@Deprecated(
    "Replaced by DropdownMenu with properties parameter",
    ReplaceWith(
        "DropdownMenu(expanded, onDismissRequest, modifier, offset, " +
            "androidx.compose.ui.window.PopupProperties(focusable = focusable), " +
            "content)"
    ),
    level = DeprecationLevel.HIDDEN

fun DropdownMenu(
    expanded: Boolean,
    onDismissRequest: () -> Unit,
    focusable: Boolean = true,
    modifier: Modifier = Modifier,
    offset: DpOffset = DpOffset(0.dp, 0.dp),
    content: @Composable ColumnScope.() -> Unit
)
@Composable
@Deprecated(
    level = DeprecationLevel.HIDDEN,
    replaceWith =
        ReplaceWith(
            expression =
                "DropdownMenu(expanded,onDismissRequest, modifier, offset, " +
                    "rememberScrollState(), properties, content)",
            "androidx.compose.foundation.rememberScrollState"
        ),
    message = "Replaced by a DropdownMenu function with a ScrollState parameter"

fun DropdownMenu(
    expanded: Boolean,
    onDismissRequest: () -> Unit,
    modifier: Modifier = Modifier,
    offset: DpOffset = DpOffset(0.dp, 0.dp),
    properties: PopupProperties = PopupProperties(focusable = true),
    content: @Composable ColumnScope.() -> Unit
)
@Composable
@Deprecated(
    level = DeprecationLevel.HIDDEN,
    replaceWith =
        ReplaceWith(
            expression =
                "DropdownMenu(\n" +
                    "    expanded = expanded,\n" +
                    "    onDismissRequest = onDismissRequest,\n" +
                    "    modifier = modifier,\n" +
                    "    offset = offset,\n" +
                    "    scrollState = scrollState,\n" +
                    "    properties = properties,\n" +
                    "    shape = MenuDefaults.shape,\n" +
                    "    containerColor = MenuDefaults.containerColor,\n" +
                    "    tonalElevation = MenuDefaults.TonalElevation,\n" +
                    "    shadowElevation = MenuDefaults.ShadowElevation,\n" +
                    "    border = null,\n" +
                    "    content = content,\n" +
                    ")",
        ),
    message =
        "Maintained for binary compatibility. Use overload with parameters for shape, " +
            "color, elevation, and border."

fun DropdownMenu(
    expanded: Boolean,
    onDismissRequest: () -> Unit,
    modifier: Modifier = Modifier,
    offset: DpOffset = DpOffset(0.dp, 0.dp),
    scrollState: ScrollState = rememberScrollState(),
    properties: PopupProperties = PopupProperties(focusable = true),
    content: @Composable ColumnScope.() -> Unit
)
@Composable
fun DropdownMenu(
    expanded: Boolean,
    onDismissRequest: () -> Unit,
    modifier: Modifier,
    offset: DpOffset,
    scrollState: ScrollState,
    properties: PopupProperties,
    shape: Shape,
    containerColor: Color,
    tonalElevation: Dp,
    shadowElevation: Dp,
    border: BorderStroke?,
    content: @Composable ColumnScope.() -> Unit
)

Code Examples

@Composable
@Sampled
@Preview
fun MenuSample() {
    var expanded by remember { mutableStateOf(false) }

    Box(modifier = Modifier.fillMaxSize().wrapContentSize(Alignment.TopStart)) {
        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) }
            )
        }
    }
}
@Composable
@Sampled
@Preview
fun MenuWithScrollStateSample() {
    var expanded by remember { mutableStateOf(false) }
    val scrollState = rememberScrollState()
    Box(modifier = Modifier.fillMaxSize().wrapContentSize(Alignment.TopStart)) {
        IconButton(onClick = { expanded = true }) {
            Icon(Icons.Default.MoreVert, contentDescription = "Localized description")
        }
        DropdownMenu(
            expanded = expanded,
            onDismissRequest = { expanded = false },
            scrollState = scrollState
        ) {
            repeat(30) {
                DropdownMenuItem(
                    text = { Text("Item ${it + 1}") },
                    onClick = { /* TODO */ },
                    leadingIcon = { Icon(Icons.Outlined.Edit, contentDescription = null) }
                )
            }
        }
        LaunchedEffect(expanded) {
            if (expanded) {
                // Scroll to show the bottom menu items.
                scrollState.scrollTo(scrollState.maxValue)
            }
        }
    }
}