My Goal:
I'm trying to implement an autocomplete TextField in Jetpack Compose. The desired behavior is:
A user starts typing in a
TextField.A list of suggestions, filtered by the user's input, appears directly below the
TextField.Crucially, the user must be able to continue typing to refine their search while the suggestion list is visible. The suggestion list should not be a modal popup and should not steal focus from the
TextField.
What I've Tried:
My first attempt was with ExposedDropdownMenuBox. This seems like the natural choice for a dropdown, but it fails for a live-search implementation because once the menu is expanded, it becomes impossible to type in the TextField. The menu seems to grab all the focus.
Here's the anonymized code for this approach:
The following Function is used inside of an AlertDialog
// Data class for the items data class DataItem(val id: String, val displayName: String) /** * Example implementation */ @OptIn(ExperimentalMaterial3Api::class) @Composable fun SearchableDropdownExample() { // Example Data val allItems = remember { listOf( DataItem("1", "Apfel"), DataItem("2", "Banane"), DataItem("3", "Kirsche"), DataItem("4", "Dattel"), DataItem("5", "Holunderbeere") ) } // States for the Dropdown var isDropdownExpanded by remember { mutableStateOf(false) } var selectedDataItem by remember { mutableStateOf<DataItem?>(null)} var searchText by remember { mutableStateOf("") } val focusManager = LocalFocusManager.current // Filtert die Element-Liste basierend auf der Suchanfrage val filteredItems = remember(searchText, allItems) { if (searchText.isBlank()) { allItems } else { allItems.filter { it.displayName.contains(searchText, ignoreCase = true) } } } Column(verticalArrangement = Arrangement.spacedBy(8.dp)) { // Das durchsuchbare Dropdown-Menü ExposedDropdownMenuBox( expanded = isDropdownExpanded, onExpandedChange = { isDropdownExpanded = !isDropdownExpanded } ) { OutlinedTextField( value = searchText, onValueChange = { searchText = it selectedDataItem = null // Auswahl zurücksetzen, wenn der Nutzer tippt isDropdownExpanded = true // Menü offen halten }, label = { Text("Element auswählen") }, placeholder = { Text("Element suchen...") }, trailingIcon = { ExposedDropdownMenuDefaults.TrailingIcon(expanded = isDropdownExpanded) }, modifier = Modifier .menuAnchor() .fillMaxWidth() ) if (filteredItems.isNotEmpty()) { ExposedDropdownMenu( expanded = isDropdownExpanded, onDismissRequest = { isDropdownExpanded = false } ) { filteredItems.forEach { item -> DropdownMenuItem( text = { Text(item.displayName) }, onClick = { selectedDataItem = item searchText = item.displayName // Textfeld mit Auswahl füllen isDropdownExpanded = false focusManager.clearFocus() } ) } } } } } } My Question:
How can I implement a searchable dropdown or autocomplete TextField in Jetpack Compose where the user can continue typing while the suggestion list is visible? Is there a standard Composable or an idiomatic pattern for this that avoids the focus-stealing issue I'm seeing with ExposedDropdownMenuBox?