Flutter - Create Number Only TextField/TextFormField

This tutorial shows you how to create a TextField or TextFormField that accepts only numbers.

It's quite common for an application to have an input field that accepts number only inputs. Flutter doesn't have a field widget that's dedicated for numeric value. However, you can use a TextField or TextFormField. There are some adjustments that you have to do in order to make it accepts number only values.

Set Keyboard Type to Number

If a field only accepts number values, it would be better to show a keyboard with related keys only. Non-related keys such as alphabetic characters and symbols other than -, , and . should not be displayed to users. Ideally, it should show a numeric pad. By showing the appropriate keyboard, users can type faster and more conveniently. In addition, it also prevents the users from typing unwanted characters.

To set the keyboard type, you can pass the keyboardType argument and set the value to TextInputType.number, which is a static constant for creating TextInputType optimized for numerical information. Below is the example on a TextField

  TextField(
    keyboardType: TextInputType.number,
    // other arguments
  )

The usage for the TextFormField is very similar.

  TextFormField(
    keyboardType: TextInputType.number,
    // other arguments
  )

There is also a const constructor numberWithOptions that allows you to specify whether the keyboard type should allow signed and decimal numbers.

  const TextInputType.numberWithOptions({
    bool signed = false,
    bool decimal = false,
  })

If you want the keyboard to support inputting signed numbers, you can set the signed argument to true. To allow inputting decimal values, set the decimal argument to true.

  TextField(
    keyboardType: const TextInputType.numberWithOptions(
      signed: true,
      decimal: true,
    ),
    // other arguments
  )

Using TextInputType.number is actually the same as using TextInputType.numberWithOptions without passing any argument which means both signed and decimal values are set to true.

However, even if the signed and decimal values are set to false, the - and . (or , depending on the locale) keys are still displayed on many devices. In addition, setting the keyboard type only affects what keys are shown to the users. It doesn't restrict or sanitize the value on the input field. That means the users can paste a non-numeric value to the field. To handle that, we need to filter the input which is going to be explained in the next section.

Format Numeric Input

For each TextField or TextFormField, Flutter allows you to add some TextInputFormatters by passing them as the inputFormatters argument. A TextInputFormatter can be used to provide validation and formatting when a field is being edited. It's invoked every time the text on the field changes. The TextInputFormatter has a constructor named allow which creates the formatter using a pattern. You can utilize it for sanitizing the value. If the new value contains an unwanted character or doesn't comply with a given pattern, just ignore the update and keep the old value.

Unsigned Integer Numbers

For unsigned integers, the only allowed characters are digits. For this case, you can use FilteringTextInputFormatter.digitsOnly, which is a static variable that uses RegExp(r'[0-9]') pattern.

  TextField(
    inputFormatters: [
      FilteringTextInputFormatter.digitsOnly,
    ],
    // other arguments
  )

Output:

Flutter - Text Field - Unsigned Integer

Unsigned Double Numbers

For unsigned doubles (numbers with decimal point), you can use the below regex. It accepts a string started with one or more digits, followed by an optional decimal point, and followed by zero or more digits.

  TextField(
    inputFormatters: [
      FilteringTextInputFormatter.allow(RegExp(r'^\d+\.?\d*')),
    ],
    // other arguments
  )

Output:

Flutter - Text Field - Unsigned Double

It's also possible to limit the number of digits after the decimal point by adding the limit in the pattern.

  TextField(
    inputFormatters: [
      FilteringTextInputFormatter.allow(RegExp(r'^\d+\.?\d{0,2}')),
    ],
    // other arguments
  )

Output:

Flutter - Text Field - Unsigned Double with Precision

Signed Integer Numbers

For signed integers, the regex should include an optional - at the start, followed by the digits.

  TextField(
    inputFormatters: [
      FilteringTextInputFormatter.allow(RegExp(r'^\-?\d*')),
    ],
    // other arguments
  )

Output:

Flutter - Text Field - Signed Integer

Signed Double Numbers

For signed doubles, the regex should include an optional - at the start. Then, it's followed by the same regex used for signed decimal numbers which must be set to optional because in many cases the users will only input the - sign at first. Below is the example where the number of decimal places is not limited.

  TextField(
    inputFormatters: [
      FilteringTextInputFormatter.allow(RegExp(r'^\-?(\d+\.?\d*)?')),
    ],
    // other arguments
  )

Output:

Flutter - Text Field - Signed Double

Below is the example for signed doubles where the number of decimal places is limited.

  TextField(
    inputFormatters: [
      FilteringTextInputFormatter.allow(RegExp(r'^\-?(\d+\.?\d{0,2})?')),
    ],
    // other arguments
  )

Output:

Flutter - Text Field - Signed Double with Precision

Summary

To create a TextField or a TextFormField that accepts numbers only, first you should set the keyboard type to display a numeric pad. In addition, you have to use a TextInputFormatter for validating that the input value matches a certain pattern. This tutorial provides the patterns to use for unsigned and signed integer and double numbers.

You can also read about: