-
Notifications
You must be signed in to change notification settings - Fork 6
Description
Environment
I'm using io.github.dokar3:chiptextfield-m3 on version 0.7.0-alpha05. I discovered this issue using Interactive Mode Preview in Android Studio Meerkat | 2024.3.1 Patch 1 (Build #AI-243.24978.46.2431.13208083), but I suspect it would manifest in an actual device as well.
Issue
When the Input component loses focus, textFieldFocusState does not update. This can cause an issue where state.focusTextField() becomes a no-op and does not move focus to the text field as expected.
Reproduction
- Add a chip to the input field
- Invoke
state.focusTextField()to setstate.textFieldFocusStatetoTextFieldFocusState.Focused - Move focus to a different component
- Invoke
state.focusTextField()again. Sincestate.textFieldFocusStateis alreadyTextFieldFocusState.Focused, the snapshotFlow that uses it will not emit another value. - Trying to type into the input field will no longer work. Instead, the first chip is focused.
Proposed solutions
Would it be feasible to either
- update
textFieldFocusStatewhenever the focus changes, or - change the way
textFieldFocusStateis consumed so that duplicate values are still emitted?
I'm fairly new to Android development, so there might be a better fix.
Code to reproduce
I ran into this issue when building an autocomplete menu that uses ChipTextField. Below is a simplified version. I can share the full code if necessary.
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun ChipAutocompleteInputField() {
val state = rememberChipTextFieldState<Chip>()
var value by remember { mutableStateOf("") }
var expanded by remember { mutableStateOf(false) }
val options = listOf("first", "second", "third")
Button(onClick = { state.focusTextField() }) {
Text("Invoke focusTextField")
}
ExposedDropdownMenuBox(expanded = expanded, onExpandedChange = { expanded = it }) {
ChipTextField(
state = state,
value = value,
onValueChange = { value = it },
onSubmit = ::Chip,
label = { Text("example") },
innerModifier = Modifier.menuAnchor(MenuAnchorType.PrimaryEditable),
)
ExposedDropdownMenu(expanded = expanded, onDismissRequest = { expanded = false }) {
options.forEach { option ->
DropdownMenuItem(
onClick = {
value = ""
expanded = false
state.addChip(Chip(option))
state.focusTextField()
},
text = { Text(option) },
)
}
}
}
}
@Preview(showBackground = true, widthDp = 300, heightDp = 600)
@Composable
fun ChipAutocompleteInputFieldPreview() {
AppTheme(darkTheme = true) {
Column {
ChipAutocompleteInputField()
}
}
}
Workaround
Changing the Button's onclick to the following fixes the issue.
MainScope().launch {
if (state.isTextFieldFocused) {
state.clearTextFieldFocus()
awaitFrame() // Changes seem to be ignored without this, I guess it only checks once per frame?
}
state.focusTextField()
}This changes textFieldFocusState so that calling focusTextField will emit a new value, but it's hacky and causes issues if the user is typing quickly.