Home > Software engineering >  Limit number of digits before and after decimals in text field in jetpack compose
Limit number of digits before and after decimals in text field in jetpack compose

Time:11-23

How can I make the TextField accept only integers as input and how can I limit the number of digits before decimal to 3 and after decimal to 2?

For example NNN.NN where N is the digit.

CodePudding user response:

The first step would be to set keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number) for the TextField. This will open numeric keypad when the TextField is focused.

Now the problem is that TextField doesn't do any validation by itself (unlike the EditText with inputType="number"). User can type any character present on the keyboard (like commas, spaces, dashes, and even multiple decimals). You need to do all this validation by yourself.

Try this code:

var number by remember { mutableStateOf("") }
TextField(
    value = number,
    onValueChange = { number = getValidatedNumber(it) },
    keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number)
)
fun getValidatedNumber(String text): String {
    // Start by filtering out unwanted characters like commas and multiple decimals
    val filteredChars = text.filterIndexed { index, c ->
        c in "0123456789" ||                      // Take all digits
        (c == '.' && text.indexOf('.') == index)  // Take only the first decimal
    }
    // Now we need to remove extra digits from the input
    return if(filteredChars.contains('.')) {
        val beforeDecimal = filteredChars.substringBefore('.')
        val afterDecimal = filteredChars.substringAfter('.')
        beforeDecimal.take(3)   "."   afterDecimal.take(2)    // If decimal is present, take first 3 digits before decimal and first 2 digits after decimal
    } else {
        filteredChars.take(3)                     // If there is no decimal, just take the first 3 digits
    }
}

I haven't tested this code but I think it should work for most of the cases. It will make sure that final input doesn't exceed the original constraints but it might lead to some unexpected behavior. For example:

  • If the current text is "123.45" and the user places the cursor after decimal and removes the decimal. In that case the new text will become "123" i.e. "45" will get removed because "12345" breaks the "3 digits before decimal constraint".
  • If the current text is "123" and user places cursor at the start and types "4", the next text will be "412". "3" will be removed.

For these corner cases where user changes cursor position and types stuff, you will have to decide what the correct behavior should be (like in my 1st example, you might choose to not allow decimal removal and keep the original text). You will have to add such conditions in the getValidatedNumber function based on your exact requirements. One workaround that I some times use here is to disable cursor position change i.e. cursor will always remain at the end and cannot be brought to arbitrary indices.

  • Related