下拉菜单主要 以下三种实现:
@ExperimentalMaterialApi
@Composable
fun ExposedDropdownMenuBox(
expanded: Boolean,
onExpandedChange: (Boolean) -> Unit,
modifier: Modifier = Modifier,
content: @Composable ExposedDropdownMenuBoxScope.() -> Unit
)
实现代码:
@file:OptIn(ExperimentalMaterial3Api::class)
package com.example.myapplication.ui.menu
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun DropdownMenuDemo() {
Column(
modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
DropdownMenuSample()
ExposedDropdownMenuSample()
EditableExposedDropdownMenuSample()
}
}
@Composable
fun DropdownMenuSample() {
var selectedOption by remember { mutableStateOf("Option 1") }
var isExposedDropdownOpen by remember { mutableStateOf(false) }
Column() {
DropdownMenu(
expanded = isExposedDropdownOpen,
onDismissRequest = { isExposedDropdownOpen = false }
) {
DropdownMenuItem(onClick = {
selectedOption = "Option 1"
isExposedDropdownOpen = false
}, text = {
Text("Option 1")
})
DropdownMenuItem(onClick = {
selectedOption = "Option 2"
isExposedDropdownOpen = false
}, text = {
Text("Option 2")
})
DropdownMenuItem(onClick = {
selectedOption = "Option 3"
isExposedDropdownOpen = false
}, text = {
Text("Option 3")
})
}
Button(onClick = {
isExposedDropdownOpen = true
}) {
Text(text = "点击")
}
}
}
@Composable
fun ExposedDropdownMenuSample() {
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]) }
// We want to react on tap/press on TextField to show menu
ExposedDropdownMenuBox(
expanded = expanded,
onExpandedChange = {
expanded = !expanded
}
) {
TextField(
readOnly = true,
value = selectedOptionText,
onValueChange = { },
label = { Text("Label") },
trailingIcon = {
ExposedDropdownMenuDefaults.TrailingIcon(
expanded = expanded
)
},
colors = ExposedDropdownMenuDefaults.textFieldColors(),
modifier = Modifier.menuAnchor()
)
ExposedDropdownMenu(
expanded = expanded,
onDismissRequest = {
expanded = false
},
) {
options.forEach { selectionOption ->
DropdownMenuItem(
text = {
Text(selectionOption)
},
onClick = {
selectedOptionText = selectionOption
expanded = false
}
)
}
}
}
}
@Composable
fun EditableExposedDropdownMenuSample() {
val options = listOf("Option 1", "Option 2", "Option 3", "Option 4", "Option 5")
var expanded by remember { mutableStateOf(false) }
var selectedOptionText by remember { mutableStateOf("") }
ExposedDropdownMenuBox(
expanded = expanded,
onExpandedChange = {
expanded = !expanded
}
) {
TextField(
value = selectedOptionText,
onValueChange = {
selectedOptionText = it
expanded = true
},
label = { Text("Label") },
trailingIcon = {
ExposedDropdownMenuDefaults.TrailingIcon(
expanded = expanded
)
},
colors = ExposedDropdownMenuDefaults.textFieldColors(),
modifier = Modifier.menuAnchor()
)
// filter options based on text field value
val filteringOptions =
options.filter { it.contains(selectedOptionText, ignoreCase = true) }
if (filteringOptions.isNotEmpty()) {
ExposedDropdownMenu(
expanded = expanded,
onDismissRequest = {
expanded = false
}
) {
filteringOptions.forEach { selectionOption ->
DropdownMenuItem(
text = {
Text(text = selectionOption)
},
onClick = {
selectedOptionText = selectionOption
expanded = false
}
)
}
}
}
}
}
@Preview
@Composable
fun DropdownMenuDemoPreview() {
DropdownMenuDemo()
}