I'm working on a dropdown selector. Has anyone com...
# compose-desktop
s
I'm working on a dropdown selector. Has anyone come up with an acceptable solution? My current implementation in thread.
Copy code
@Composable
actual fun DropdownSelector(
    modifier: Modifier,
    selectedIndex: Int,
    items: List<String>,
    label: String,
    errorRes: StringResource?,
    onChange: (Int) -> Unit,
) {
    var expanded by remember { mutableStateOf(false) }
    val selectedItemText = when {
        items.isEmpty() -> ""
        selectedIndex < 0 -> items[0]
        else -> items[selectedIndex]
    }
    val indicatorColor = when {
        errorRes != null -> MaterialTheme.colors.error.copy(alpha = ContentAlpha.high)
        expanded -> MaterialTheme.colors.primary.copy(alpha = ContentAlpha.high)
        else -> MaterialTheme.colors.onSurface.copy(alpha = 0.42f)
    }
    Column(modifier) {
        OutlinedTextField(
            value = selectedItemText,
            label = { Text(label) },
            onValueChange = {},
            readOnly = true,
            trailingIcon = {
                IconButton(
                    onClick = {
                        expanded = !expanded
                    },
                ) {
                    Icon(
                        imageVector = Icons.Default.ArrowDropDown,
                        contentDescription = "select",
                        Modifier.rotate(
                            if (expanded) 180f else 0f
                        ),
                    )
                }
            },
            isError = errorRes != null
        )
        DropdownMenu(
            expanded = expanded,
            onDismissRequest = {
                expanded = false
            },
        ) {
            items.forEachIndexed { index, item ->
                DropdownMenuItem(
                    onClick = {
                        onChange(index)
                        expanded = false
                    }
                ) {
                    Text(text = item)
                }
            }
        }
        if (errorRes != null) {
            Text(
                text = label,
                modifier = Modifier
                    .background(color = MaterialTheme.colors.background),
                style = MaterialTheme.typography.caption.copy(color = indicatorColor)
            )
        }
    }
}
clicking on the
IconButton
while the popup is showing, causes both actions to happen, which is clearly a mistake. Unfortunately the
onDismissRequest
is called first.
o
Can’t you set
enabled = !expanded
on icon button?
s
Yes, but clicking on it triggers the
onClick
for the icon button and the
onDismissRequest
for the
DropdownMenu
o
But if you disable it, it shouldn’t produce the click event?
s
oh, sorry, misread that.
That makes a lot of sense. Let me try it.
o
Could change appearance, though
s
True, it does. It's not a perfect solution, but it's good enough.
Thank you!
o
As a dirty hack, you can copy implementation of
IconButton
, it’s trivial, and remove the line about providing disabled ContentAlpha 🙂
But I’m sure there should be “proper” way to deal with states like this.
s
There's too many things about this implementation that I don't like. I'd prefer that clicking on the textfield opened the menu, but trying to implement that was even more buggy.
o
Also, I wonder if
DropDownMenu
should be capturing mouse input and consume click outside cc @Igor Demin
s
That would make sense to me.