DropdownMenu

Functions summary

Unit
@Composable
DropdownMenu(
    expanded: Boolean,
    onDismissRequest: () -> Unit,
    modifier: Modifier,
    offset: DpOffset,
    scrollState: ScrollState,
    properties: PopupProperties,
    content: @Composable ColumnScope.() -> Unit
)

Material Design dropdown menu

Cmn
android

Functions

@Composable
fun DropdownMenu(
    expanded: Boolean,
    onDismissRequest: () -> Unit,
    modifier: Modifier = Modifier,
    offset: DpOffset = DpOffset(0.dp, 0.dp),
    scrollState: ScrollState = rememberScrollState(),
    properties: PopupProperties = DefaultMenuProperties,
    content: @Composable ColumnScope.() -> Unit
): Unit

Material Design dropdown menu

A dropdown menu is a compact way of displaying multiple choices. It appears upon interaction with an element (such as an icon or button) or when users perform a specific action.

Menus
image

A DropdownMenu behaves similarly to a Popup, and will use the position of the parent layout to position itself on screen. Commonly a DropdownMenu will be placed in a androidx.compose.foundation.layout.Box with a sibling that will be used as the 'anchor'. Note that a DropdownMenu by itself will not take up any space in a layout, as the menu is displayed in a separate window, on top of other content.

The content of a DropdownMenu will typically be DropdownMenuItems, as well as custom content. Using DropdownMenuItems will result in a menu that matches the Material specification for menus. Also note that the content is placed inside a scrollable Column, so using a androidx.compose.foundation.lazy.LazyColumn as the root layout inside content is unsupported.

onDismissRequest will be called when the menu should close - for example when there is a tap outside the menu, or when the back key is pressed.

DropdownMenu changes its positioning depending on the available space, always trying to be fully visible. Depending on layout direction, first it will try to align its start to the start of its parent, then its end to the end of its parent, and then to the edge of the window. Vertically, it will try to align its top to the bottom of its parent, then its bottom to top of its parent, and then to the edge of the window.

An offset can be provided to adjust the positioning of the menu for cases when the layout bounds of its parent do not coincide with its visual bounds.

Example usage:

import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.material.Divider
import androidx.compose.material.DropdownMenu
import androidx.compose.material.DropdownMenuItem
import androidx.compose.material.Icon
import androidx.compose.material.IconButton
import androidx.compose.material.Text
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.MoreVert
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier

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(onClick = { /* Handle refresh! */ }) { Text("Refresh") }
        DropdownMenuItem(onClick = { /* Handle settings! */ }) { Text("Settings") }
        Divider()
        DropdownMenuItem(onClick = { /* Handle send feedback! */ }) { Text("Send Feedback") }
    }
}

Example usage with a ScrollState to control the menu items scroll position:

import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.foundation.rememberScrollState
import androidx.compose.material.DropdownMenu
import androidx.compose.material.DropdownMenuItem
import androidx.compose.material.Icon
import androidx.compose.material.IconButton
import androidx.compose.material.Text
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.MoreVert
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier

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(onClick = { /* Handle item! */ }) { Text("Item ${it + 1}") }
        }
    }
    LaunchedEffect(expanded) {
        if (expanded) {
            // Scroll to show the bottom menu items.
            scrollState.scrollTo(scrollState.maxValue)
        }
    }
}
Parameters
expanded: Boolean

whether the menu is expanded or not

onDismissRequest: () -> Unit

called when the user requests to dismiss the menu, such as by tapping outside the menu's bounds

modifier: Modifier = Modifier

Modifier to be applied to the menu's content

offset: DpOffset = DpOffset(0.dp, 0.dp)

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.

scrollState: ScrollState = rememberScrollState()

a ScrollState to used by the menu's content for items vertical scrolling

properties: PopupProperties = DefaultMenuProperties

PopupProperties for further customization of this popup's behavior

content: @Composable ColumnScope.() -> Unit

the content of this dropdown menu, typically a DropdownMenuItem