0

I am working on customizing TextField in Jetpack Compose, I want restrict the input from the user to numbers, commas or a single dot.

The regular expression that I am currently using is val expression = Regex("[\\d,.]+") . It works fine for numbers and commas but I am able to enter multiple dots(.) which I don't want. I want one single dot only. Here is my Jetpack Compose code.

    val expression = Regex("[\\d,.]+")

    val keyboardOptions = KeyboardOptions(
        keyboardType = KeyboardType.Number,
        imeAction = ImeAction.Done
    )

    TextField(
        value = text,
        onValueChange = {
            if (it.isEmpty() || it.matches(expression))
               onValueChange(it)
        },
        keyboardOptions = keyboardOptions,
        keyboardActions = KeyboardActions(
            onDone = {  }
        ),
    )
Arshdeep_somal
  • 206
  • 1
  • 13
  • 1
    This will fly in the face of locale parsing (e.g. `123.456,70` in France). But for the direct question asked, you could just consider the period separately (after all, it is unique!). Consider as well that grouping separators (`,`) should not appear after the decimal separator (`.`), and you end up with: `[\\d,]+(\.\\d+)?`. It can be refined further, but I would look into something else for parsing numbers like this (e.g. `BigDecimal` or `parseDouble`). – Rogue Aug 22 '23 at 14:58
  • If you are validating numbers, just use `NumberFormat`. No need to write your own regex. – Jorn Aug 22 '23 at 15:03
  • 1
    In general, there's no need to restrict user input like that. Just have them type the number however they like, parse it, and then display it in your specified way. – Jorn Aug 22 '23 at 15:04

1 Answers1

1

Actually you are accepting only numbers using keyboard options and that's why you don't need to validate digits in regex... but for the question you have asked you can use this regex:

val expression = Regex("[\\d,]*[.]?[\\d,]*"
  • Question Mark(?) is for zero or one occurrence
  • Asterisk(*) is for zero or more occurrences
  • Plus(+) is for one or more occurrences

NOTE: This will accept dot(.) and comma(,) as first and last character as well.

And you also don't need to validate it.isEmpty() in onValueChange lambda because it will also handled using the regex as it also accepts empty strings.

Atul Sharma
  • 399
  • 3
  • 12
  • 1
    No sense putting the comma after the `[.]?` imo, since any numbers/commas will get picked up by the previous `[\\d,]*` up to the first `.`. For example, `123,456.789,123` doesn't make much sense as a single number, which this pattern permits. – Rogue Aug 23 '23 at 12:29
  • Yes, you are right @Rogue, there are many awkward strings which satisfies the regex. I have also marked a note in my question as well for example, `,12,34.` this also make no sense. But for the sake of the question asked I have given that regex. – Atul Sharma Aug 24 '23 at 04:34