I am trying to achieve search functionality in compose using DropDownItem
but it is displaying below OutlineTextField
. All the available option is not displaying over the content like DropDown menu.
Effort 1: Tried using DropDownMenu
but in that case, the text field was not in the correct location and bounced over the screen depending on the list of options. (Working as a popUp)
Effort 2: I can not use ExposedDropDownMenuBox
as it will require M3 and I am currently using M2 in my project and we can not convert the whole project to M3 for this.
Any suggestions or solutions would be greatly appreciated.
Here is my SearchField
composable look like
@Composable
fun SearchField(
optionList: List<Address>,
label: String,
searchText: String,
isSearching: Boolean,
onValueChange: (String) -> Unit,
) {
var expanded by remember { mutableStateOf(true) }
var textfieldSize by remember { mutableStateOf(Size.Zero) }
var selectedText by remember { mutableStateOf("") }
val focusRequester = FocusRequester()
// DropdownMenu(
// modifier = Modifier
// .fillMaxWidth()
// .onGloballyPositioned { coordinates ->
// //This value is used to assign to the DropDown the same width
// textfieldSize = coordinates.size.toSize()
// },
// expanded = true,
//// properties = PopupProperties(usePlatformDefaultWidth = true),
// onDismissRequest = {
// }
// ) {
OutlinedTextField(
value = searchText,
enabled = true,
onValueChange = {
selectedText = it
onValueChange(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) },
)
if (expanded) {
if (isSearching) {
CircularProgressIndicator()
}
optionList.forEach { address ->
DropdownMenuItem(
onClick = {
println("Selected Address : ${address.addressLine1}")
selectedText = address.addressLine1
expanded = !expanded
}
) {
Text(text = address.addressLine1)
}
}
}
// }
}
Here's what it look like right now
Here is the try with Box
Box {
// Address 1
EditableRow(
// modifier = Modifier.focusRequester(focusRequester),
value = state.address1.value.toString(),
onValueChange = {
state.address1.value = it
isSearchExpanded = true
customerDetailsViewModel.onSearchText(it)
},
error = state.address1.error.orEmpty(),
hintText = stringResource(id = R.string.address),
enabled = state.isAddressEditable,
trailingIcon = {
if (isTrailingVisible.value && state.isAddressEditable) {
CloseIcon(modifier = Modifier.clickable { isSearchExpanded = !isSearchExpanded }) {
state.address1.value = ""
focusRequester.requestFocus()
}
}
},
keyboardOptions = KeyboardOptions.Default.copy(
imeAction = ImeAction.Done,
),
keyboardActions = KeyboardActions(onDone = {
focusManager.clearFocus()
})
)
DropdownMenu(modifier = Modifier
.fillMaxWidth(),
expanded = isSearchExpanded, onDismissRequest = { }) {
searchList.forEach { address ->
DropdownMenuItem(
onClick = {
state.address1.value = address.addressLine1
// selectedText = address.addressLine1
isSearchExpanded = !isSearchExpanded
focusManager.clearFocus()
}
) {
Text(text = address.addressLine1)
}
}
}
}
The
ExposedDropDownMenuBox
exists also for M2 and it is the best option.In your solution you have to add the
DropdownMenu
if you want to display the menu in a separate window, on top of other content.Something like: