I am currently observing some strange behavior when using an OutlinedTextField
inside of an ExposedDropdownMenuBox
. If I have already clicked into the OutlinedTextField
once, the focus always jumps back to it when I click into another field or sometimes when I'm simply scrolling through my view - preferably after the keyboard is closed manually, if the keyboard keeps visible I can click into the other input fields without any problem.
Has anyone experienced a similar behaviour and knows how to fix this?
I'm using version 1.3.1 of androidx.compose.material:material
My Composable
looks like this:
@OptIn(ExperimentalMaterialApi::class)
@Composable
fun ContributorComposable(contributor: Contributor, logbookEntryState: LogbookEntryState, enabled: Boolean) {
Spacer(modifier = Modifier.height(8.dp))
val addContributor: @Composable () -> Unit = {
IconButton(onClick = { logbookEntryState.contributors.add(Contributor()) }) {
Icon(imageVector = Icons.Filled.Add, contentDescription = "")
}
}
var expanded by remember { mutableStateOf(false) }
val options = logbookEntryState.contributorsDropDownList
Column(modifier = Modifier.fillMaxWidth()) {
Row(verticalAlignment = CenterVertically, horizontalArrangement = Arrangement.End, modifier = Modifier.fillMaxWidth()) {
Spacer(modifier = Modifier.width(40.dp))
ExposedDropdownMenuBox(
expanded = expanded,
onExpandedChange = { expanded = !expanded && enabled },
modifier = Modifier.focusable(false)
) {
Row(verticalAlignment = CenterVertically, horizontalArrangement = Arrangement.End, modifier = Modifier.fillMaxWidth()) {
OutlinedTextField(
colors = if (
contributor.company.value.isNotBlank() ||
contributor.registrationNumber.value.isNotBlank() ||
contributor.userCertificationNumber.value.isNotBlank() ||
contributor.companyCertificationNumber.value.isNotBlank() ||
contributor.userFullname.value.isNotBlank()
) TextFieldDefaults.outlinedTextFieldColors(unfocusedBorderColor = db_primary_red) else TextFieldDefaults.outlinedTextFieldColors(),
modifier = Modifier
.weight(1f),
value = contributor.userFullname.value,
onValueChange = { newText ->
contributor.userFullname.value = newText
viewModel.findContributorByName(logbookEntryState, newText)
expanded = true
},
label = { Text(stringResource(id = R.string.logbook_entry_create_contributors)) },
trailingIcon = if (enabled) addContributor else null,
enabled = enabled,
)
if (enabled && logbookEntryState.contributors.size > 1) {
IconButton(onClick = { logbookEntryState.contributors.remove(contributor) }, modifier = Modifier.width(40.dp)) {
Icon(imageVector = Icons.Filled.Delete, contentDescription = "")
}
} else {
Spacer(modifier = Modifier.width(40.dp))
}
}
if (options.isNotEmpty())
ExposedDropdownMenu(
expanded = expanded,
modifier = Modifier.background(db_secondary_white),
onDismissRequest = { expanded = false },
) {
options.forEach { selectionOption ->
DropdownMenuItem(
modifier = Modifier
.background(db_secondary_white)
.exposedDropdownSize(true),
onClick = {
contributor.internalId = selectionOption.internalId
contributor.userFullname.value = selectionOption.userFullname.value
contributor.userFullnameErrorMessage.value = ""
contributor.company.value = selectionOption.company.value
contributor.companyErrorMessage.value = ""
contributor.registrationNumber.value = selectionOption.registrationNumber.value
contributor.registrationNumberErrorMessage.value = ""
contributor.userCertificationNumber.value = selectionOption.userCertificationNumber.value
contributor.userCertificationNumberErrorMessage.value = ""
contributor.companyCertificationNumber.value = selectionOption.companyCertificationNumber.value
contributor.companyCertificationNumberErrorMessage.value = ""
contributor.id = selectionOption.id
contributor.entryId = selectionOption.entryId
contributor.createdBy = selectionOption.createdBy
contributor.creationDate = selectionOption.creationDate
expanded = false
}
) {
Column(modifier = Modifier.fillMaxWidth()) {
Row(verticalAlignment = CenterVertically) {
Text(text = selectionOption.userFullname.value ?: "")
}
// if there are users with the same name, we show additional information
if (options.groupBy { it.userFullname }.size > 1) {
Row(verticalAlignment = CenterVertically) {
Text(text = selectionOption.company.value ?: "")
}
Row(verticalAlignment = CenterVertically) {
Text(text = selectionOption.registrationNumber.value ?: "")
}
if (viewModel.shouldShowCertificatenummber()) {
Row(verticalAlignment = CenterVertically) {
Text(text = selectionOption.userCertificationNumber.value ?: "")
}
}
if (viewModel.shouldShowCertificatenummber()) {
Row(verticalAlignment = CenterVertically) {
Text(text = selectionOption.companyCertificationNumber.value ?: "")
}
}
DefaultDivider()
Spacer(modifier = Modifier.height(8.dp))
}
}
}
}
}
}
}
ErrorComposable(contributor.userFullnameErrorMessage.value)
}
CustomTextField(
label = R.string.logbook_entry_create_company_contributors,
input = contributor.company,
errorMessage = contributor.companyErrorMessage,
enabled = enabled,
shouldShow = true,
mandatoryField = contributor.userFullname.value.isNotBlank(),
)
CustomTextField(
label = R.string.logbook_entry_create_registrationnr_contributors,
input = contributor.registrationNumber,
errorMessage = contributor.registrationNumberErrorMessage,
enabled = enabled,
shouldShow = viewModel.logbook?.classEntity?.hasRegistrationNumber == true,
mandatoryField = contributor.userFullname.value.isNotBlank(),
)
CustomTextField(
label = R.string.logbook_entry_create_certification_numbers_contributors,
input = contributor.userCertificationNumber,
errorMessage = contributor.userCertificationNumberErrorMessage,
enabled = enabled,
shouldShow = viewModel.shouldShowCertificatenummber(),
mandatoryField = contributor.userFullname.value.isNotBlank(),
)
CustomTextField(
label = R.string.logbook_entry_create_company_certification_numbers_contributors,
input = contributor.companyCertificationNumber,
errorMessage = contributor.companyCertificationNumberErrorMessage,
enabled = enabled,
shouldShow = viewModel.shouldShowCertificatenummber(),
mandatoryField = contributor.userFullname.value.isNotBlank(),
)
}
Since it seemed to be a focus issue with the text field inside of the
ExposedDropdownMenuBox
, I took a look at that specific class and found the part that caused the behaviour:So if
expanded
is not updated correctly and staystrue
, the view will regain the focus unintentionally.Setting
expanded
tofalse
when "leaving" the input field fixed the bevahiour: