skip to Main Content

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.

2

Answers


  1. 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(text: String): 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.

    Login or Signup to reply.
  2. As @Arpit Shukla wrote a fine function, I had an issue with starting input with a . and to have the function not allow . as a first character i’ve updated the function like so:

    private fun getValidatedNumber(text: String): String {
        val filteredChars = text.filterIndexed { index, c ->
            c.isDigit()
                    || (c == '.' && index != 0 && text.indexOf('.') == index)
                    || (c == '.' && index != 0 && text.count{ it == '.'} <=1)
        }
        // If dot is present, take first 3 digits before decimal and first 2 digits after decimal
        return if (filteredChars.count{it == '.'} == 1 ) {
            val beforeDecimal = filteredChars.substringBefore('.')
            val afterDecimal = filteredChars.substringAfter('.')
            beforeDecimal.take(3) + "." + afterDecimal.take(2)
        }
        // If there is no dot, just take the first 3 digits
        else {
            filteredChars.take(3)
        }
    }
    

    Remark i’ve used the kotlin function character.isDigit() instead of being reliant on the hardcoded values.
    I’ve added an extra check that index is not 0so the function does not allow the first input to be a ..
    I’ve also added a check that will not allow extra .‘s.

    Peace to you ✌

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search