Search with DropDownItem in OutlineTextField not overlaying over content

703 views Asked by At

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

enter image description here

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)
                }
            }
        }

    }
1

There are 1 answers

7
Gabriele Mariotti On

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:

    Box() {
        OutlinedTextField(
           //...
        )


        DropdownMenu(
            //...
        ) {

            items.forEach { label ->
                DropdownMenuItem(
                   //....
                )
            }
        }
    }