Search code examples
androiduser-interfaceautocompleteandroid-jetpack-compose

AutoComplete composable


I'm making an AutoComplete composeable function based on this answer:

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun AutoComplete(
    labelText: String,
    options: List<String>,
    value: String,
    onValueChange: (String) -> Unit,
    modifier: Modifier = Modifier,
    keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
) {
    var expanded = value.length > 2
    val filterOpts = options.filter { it.contains(value, ignoreCase = true) }

    ExposedDropdownMenuBox(
        expanded = expanded,
        onExpandedChange = { expanded = !expanded }) {
        TextField(
            label = { Text(text = labelText) },
            readOnly = true,
            value = value,
            onValueChange = onValueChange,
            colors = ExposedDropdownMenuDefaults.textFieldColors(),
            modifier = modifier.menuAnchor(),
            keyboardOptions = keyboardOptions,
        )
        if (!filterOpts.isEmpty()) {
            ExposedDropdownMenu(
                expanded = expanded,
                onDismissRequest = { expanded = false }) {
                filterOpts.forEach { option ->
                    DropdownMenuItem(
                        text = { Text(text = option) },
                        onClick = {
                            onValueChange(option)
                            expanded = false
                        }
                    )
                }
            }
        }
    }
}

I'm using it like this:

        val names = listOf("Tony Stark", "Steve Rogers", "Bruce Banner", "Natasha Romanoff")
        var name by remember {
            mutableStateOf("")
        }

        AutoComplete(
            labelText = "Name",
            options = names,
            value = name,
            onValueChange = { name = it },
        )

When I run this and focus on the Name field, I don't get an on-screen keyboard in the emulator and typing on my laptop does nothing. What am I missing? How do I focus the child TextField so that the system automatically shows a keyboard?


Solution

  • If you want a keyboard you shouldn't set readOnly = true.

    Also, I don't know what are you trying to achieve, but var expanded = value.length > 2 will keep dropdown menu open even after an option is selected. To avoid this, you can declare expanded as a regular remembered boolean:

    var expanded by remember { mutableStateOf(false) }
    

    And check value length only after a value change in TextField:

    onValueChange = {
        expanded = value.length > 2
        onValueChange(it)
    },