I'm using KeyboardType.Decimal
for the keyboard type in the keyboardOptions
entry shown below for an OutlinedTextField
, but it's allowing multiple decimals in the typed number. And doing any conversions on such an input like "2.5.8".toDouble()
throws a multiple points
exception shown below. How can I ensure that only one decimal point is allowed and any subsequent decimal key presses don't do anything?
Composable
CustomOutlinedTextField(
fieldModifier = Modifier
.width(100.dp)
.onFocusChanged {
if (!it.isFocused) {
if (mainViewModel.shoppingListItemState.value.quantity == "" || mainViewModel.shoppingListItemState.value.quantity == "0") {
mainViewModel.setStateValue(
ITEM_QUANTITY_STR,
"1"
)
}
}
}
.onPreviewKeyEvent {
if (it.key == Key.Tab && it.nativeKeyEvent.action == ACTION_DOWN) {
focusManager.moveFocus(FocusDirection.Right)
true
} else {
false
}
},
label = ITEM_QUANTITY_STR,
inputVal = mainViewModel.shoppingListItemState.value.quantity,
isSingleLine = true,
keyboardOptions = KeyboardOptions.Default.copy(
capitalization = KeyboardCapitalization.None,
autoCorrect = false,
keyboardType = KeyboardType.Decimal,
imeAction = ImeAction.Next
),
keyboardActions = KeyboardActions(
onNext = { focusManager.moveFocus(FocusDirection.Right) }
)
) { value ->
mainViewModel.setStateValue(ITEM_QUANTITY_STR, value)
}
Exception
java.lang.NumberFormatException: multiple points
CodePudding user response:
You can check the number of decimalSeparator
in the onValueChange
of your TextField
and allow only one.
It is advisable to get the decimalSeparator
instead of comparing with .
since it might change based on device Locale.
Below is a sample implementation of a TextField
which checks and allows only one decimalSeparator
.
val decimalFormat = DecimalFormat.getInstance(Locale.getDefault()) as DecimalFormat
val decimalSeparator = decimalFormat.decimalFormatSymbols.decimalSeparator
var text by remember { mutableStateOf("123") }
TextField(
value = text,
keyboardOptions = KeyboardOptions.Default.copy(
keyboardType = KeyboardType.Decimal
),
onValueChange = { value ->
val counter = value.count { it == decimalSeparator }
if (counter <= 1) { text = value }}
)
CodePudding user response:
You can use a regex in the onValueChange
to restrict the allowed character to a decimal number.
Something like:
val pattern = remember { Regex("^\\d*\\.?\\d*\$") }
TextField(
value = text,
onValueChange = {
if (it.isEmpty() || it.matches(pattern)) {
text = it
}
},
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Decimal),
)