Autofocus race condition with UI
This commit is contained in:
@@ -63,10 +63,16 @@ fun EditBillScreen(
|
|||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
val focusRequester = remember { FocusRequester() }
|
val focusRequester = remember { FocusRequester() }
|
||||||
|
|
||||||
LaunchedEffect(Unit) {
|
// The activity reads the project off the main thread and only then reports whether this is a
|
||||||
if (viewModel.isNewBill) {
|
// new bill, so the flag arrives after the first composition. Keying on it rather than on Unit
|
||||||
focusRequester.requestFocus()
|
// is what makes the effect run at all.
|
||||||
}
|
LaunchedEffect(viewModel.isNewBill) {
|
||||||
|
if (!viewModel.isNewBill) return@LaunchedEffect
|
||||||
|
// The field has to be laid out before it can take focus, which is not yet true on the
|
||||||
|
// pass that composed it. Waiting for the next frame makes this hold whether the flag was
|
||||||
|
// already set or arrived later.
|
||||||
|
withFrameNanos { }
|
||||||
|
focusRequester.requestFocus()
|
||||||
}
|
}
|
||||||
|
|
||||||
StatefulAlertDialog(
|
StatefulAlertDialog(
|
||||||
@@ -198,7 +204,7 @@ fun BillBasicInfoSection(
|
|||||||
|
|
||||||
OutlinedTextField(
|
OutlinedTextField(
|
||||||
value = viewModel.amount,
|
value = viewModel.amount,
|
||||||
onValueChange = { nv->
|
onValueChange = { nv ->
|
||||||
val filteredValue = nv.filter { it in "0123456789.+-*/" }
|
val filteredValue = nv.filter { it in "0123456789.+-*/" }
|
||||||
viewModel.amount = filteredValue
|
viewModel.amount = filteredValue
|
||||||
viewModel.updateSplits()
|
viewModel.updateSplits()
|
||||||
@@ -252,8 +258,8 @@ fun BillBasicInfoSection(
|
|||||||
placeholder = { Text(stringResource(R.string.label_what)) },
|
placeholder = { Text(stringResource(R.string.label_what)) },
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
leadingIcon = { Icon(Icons.Default.Title, contentDescription = null) },
|
leadingIcon = { Icon(Icons.Default.Title, contentDescription = null) },
|
||||||
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Next),
|
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done),
|
||||||
keyboardActions = KeyboardActions(onNext = { focusManager.moveFocus(FocusDirection.Next) })
|
keyboardActions = KeyboardActions(onDone = { focusManager.clearFocus() })
|
||||||
)
|
)
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(8.dp))
|
Spacer(modifier = Modifier.height(8.dp))
|
||||||
@@ -528,7 +534,10 @@ fun BillAdditionalDetailsSection(
|
|||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
var categoryExpanded by remember { mutableStateOf(false) }
|
var categoryExpanded by remember { mutableStateOf(false) }
|
||||||
val selectedCategory =
|
val selectedCategory =
|
||||||
categories.find { it.id == viewModel.categoryId } ?: CategoryUtils.getCategoryById(context, viewModel.categoryId)
|
categories.find { it.id == viewModel.categoryId } ?: CategoryUtils.getCategoryById(
|
||||||
|
context,
|
||||||
|
viewModel.categoryId
|
||||||
|
)
|
||||||
|
|
||||||
EditableExposedDropdownMenu(
|
EditableExposedDropdownMenu(
|
||||||
value = selectedCategory?.name ?: "",
|
value = selectedCategory?.name ?: "",
|
||||||
@@ -582,7 +591,10 @@ fun BillAdditionalDetailsSection(
|
|||||||
|
|
||||||
var pmExpanded by remember { mutableStateOf(false) }
|
var pmExpanded by remember { mutableStateOf(false) }
|
||||||
val selectedPm =
|
val selectedPm =
|
||||||
paymentModes.find { it.id == viewModel.paymentModeId } ?: CategoryUtils.getPaymentModeById(context, viewModel.paymentModeId)
|
paymentModes.find { it.id == viewModel.paymentModeId } ?: CategoryUtils.getPaymentModeById(
|
||||||
|
context,
|
||||||
|
viewModel.paymentModeId
|
||||||
|
)
|
||||||
|
|
||||||
EditableExposedDropdownMenu(
|
EditableExposedDropdownMenu(
|
||||||
value = selectedPm?.name ?: "",
|
value = selectedPm?.name ?: "",
|
||||||
|
|||||||
Reference in New Issue
Block a user