I was wondering if there is a solution for Exposed drop-down menu for jetpack compose? I couldn't find a proper solution for this component inside jetpack compose. Any help?
The M2 (starting from the version 1.1.0-alpha06
) and M3 have the implementation of ExposedDropdownMenu
based on ExposedDropdownMenuBox
with TextField
and DropdownMenu
inside.
Something like:
val options = listOf("Option 1", "Option 2", "Option 3", "Option 4", "Option 5")
var expanded by remember { mutableStateOf(false) }
var selectedOptionText by remember { mutableStateOf(options[0]) }
ExposedDropdownMenuBox(
expanded = expanded,
onExpandedChange = {
expanded = !expanded
}
) {
TextField(
readOnly = true,
value = selectedOptionText,
onValueChange = { },
label = { Text("Label") },
trailingIcon = {
ExposedDropdownMenuDefaults.TrailingIcon(
expanded = expanded
)
},
colors = ExposedDropdownMenuDefaults.textFieldColors()
)
ExposedDropdownMenu(
expanded = expanded,
onDismissRequest = {
expanded = false
}
) {
options.forEach { selectionOption ->
DropdownMenuItem(
onClick = {
selectedOptionText = selectionOption
expanded = false
}
){
Text(text = selectionOption)
}
}
}
}
If you are using M3 (androidx.compose.material3
) you have also to pass the menuAnchor
modifier to the TextField
:
ExposedDropdownMenuBox(
expanded = expanded,
onExpandedChange = { expanded = !expanded },
) {
TextField(
//...
modifier = Modifier.menuAnchor()
)
ExposedDropdownMenu(){ /*.. */ }
}
Also in M3 in the DropdownMenuItem
you have to move the content in the text
parameter:
DropdownMenuItem(
text = { Text(text = selectionOption) },
onClick = {
selectedOptionText = selectionOption
expanded = false
}
)
With the M2 version 1.0.x
there isn't a built-in component.
You can use a OutlinedTextField
+ DropdownMenu
. It is important to wrap the them in a Box
. In this way the TextField will be used as the 'anchor'.
It is just a basic (very basic) implementation:
var expanded by remember { mutableStateOf(false) }
val suggestions = listOf("Item1","Item2","Item3")
var selectedText by remember { mutableStateOf("") }
var textfieldSize by remember { mutableStateOf(Size.Zero)}
val icon = if (expanded)
Icons.Filled.ArrowDropUp //it requires androidx.compose.material:material-icons-extended
else
Icons.Filled.ArrowDropDown
Box() {
OutlinedTextField(
value = selectedText,
onValueChange = { selectedText = it },
modifier = Modifier
.fillMaxWidth()
.onGloballyPositioned { coordinates ->
//This value is used to assign to the DropDown the same width
textfieldSize = coordinates.size.toSize()
},
label = {Text("Label")},
trailingIcon = {
Icon(icon,"contentDescription",
Modifier.clickable { expanded = !expanded })
}
)
DropdownMenu(
expanded = expanded,
onDismissRequest = { expanded = false },
modifier = Modifier
.width(with(LocalDensity.current){textfieldSize.width.toDp()})
) {
suggestions.forEach { label ->
DropdownMenuItem(onClick = {
selectedText = label
}) {
Text(text = label)
}
}
}
}