Reputation: 754
I did a simple CustomTextField based on OutlinedTextField and DropDownMenu, to be able to show to user prediction when typing text. There are predictionValues: List<String>
which are compared with actual typing and visible when at least first 3 characters match. But after prediction values are showed in DropDownMenu OutlinedTextField losts focus, and I am not able to return it so user can not write further characters. Any idea ho to solve this?
@Composable
fun CustomTextField(
name: String,
value: String,
onChange: (String) -> Unit,
predictionValues: List<String> = emptyList(),
visualTransformation: VisualTransformation? = null,
modifier: Modifier = Modifier,
keyboardType: KeyboardType? = null,
imeAction: ImeAction? = null,
isEnabled: Boolean = true,
keyboardActions: KeyboardActions = KeyboardActions.Default,
trailingIcon: @Composable (() -> Unit)? = null
) {
var expanded by remember { mutableStateOf(false) }
var filteredOptions by remember { mutableStateOf<List<String>>(emptyList()) }
val focusRequester = remember { FocusRequester() }
var textFieldValue by remember { mutableStateOf(TextFieldValue(text = value)) }
fun filterOptions(query: String) {
if (query.length >= 3) {
filteredOptions = predictionValues.filter { it.contains(query, ignoreCase = true) }
expanded = filteredOptions.isNotEmpty()
} else {
expanded = false
}
}
LaunchedEffect(textFieldValue.text) {
if (textFieldValue.text != value) {
onChange(textFieldValue.text)
}
}
Column(modifier = modifier.fillMaxWidth()) {
OutlinedTextField(
value = textFieldValue,
onValueChange = { newValue ->
textFieldValue = newValue
filterOptions(newValue.text)
},
enabled = isEnabled,
modifier = Modifier
.fillMaxWidth()
.focusRequester(focusRequester),
keyboardOptions = keyboardOptions ?: KeyboardOptions(
keyboardType = keyboardType ?: KeyboardType.Text,
imeAction = imeAction ?: ImeAction.Default
),
singleLine = true,
label = { Text(text = name) },
visualTransformation = visualTransformation ?: VisualTransformation.None,
keyboardActions = keyboardActions,
trailingIcon = { trailingIcon?.invoke() }
)
DropdownMenu(
expanded = expanded,
onDismissRequest = { expanded = false }
) {
filteredOptions.forEach { option ->
DropdownMenuItem(
text = { Text(option) },
onClick = {
textFieldValue = TextFieldValue(
text = option,
selection = TextRange(option.length)
)
expanded = false
focusRequester.requestFocus()
}
)
}
}
if (expanded) {
LaunchedEffect(Unit) {
focusRequester.requestFocus()
}
}
}
}
Upvotes: 1
Views: 16