33

I want to input only decimal number in TextField in Flutter. I tried below code but that's not working. It allows alpha (a-z) and special characters.

TextField(
  controller:
      new TextEditingController(text: listDisplay[position].getBlockQty(),
  ),       
  textAlign: TextAlign.center,
  maxLines: 1,       
  keyboardType: TextInputType.numberWithOptions(
      decimal: true,
      signed: false),       
),
Sagar Zala
  • 4,854
  • 9
  • 34
  • 62

7 Answers7

41

try this:

inputFormatters: [
  FilteringTextInputFormatter.allow(RegExp(r"[0-9.]")),
  TextInputFormatter.withFunction((oldValue, newValue) {
    final text = newValue.text;
    return text.isEmpty
        ? newValue
        : double.tryParse(text) == null
            ? oldValue
            : newValue;
  }),
],

demo:

TextFormField(
  keyboardType: TextInputType.numberWithOptions(
    decimal: true,
    signed: false,
  ),
  onChanged: _yourOnChange,
  inputFormatters: [
    FilteringTextInputFormatter.allow(RegExp(r"[0-9.]")),
    TextInputFormatter.withFunction((oldValue, newValue) {
      final text = newValue.text;
      return text.isEmpty
          ? newValue
          : double.tryParse(text) == null
              ? oldValue
              : newValue;
    }),
  ],
)
Yauheni Pakala
  • 868
  • 9
  • 16
Chosan
  • 539
  • 4
  • 8
19

You can use TextInputFormatter for this case.

Here is an example for the same,

Subclass TextInputFormatter

import 'package:flutter/services.dart';

class RegExInputFormatter implements TextInputFormatter {
  final RegExp _regExp;

  RegExInputFormatter._(this._regExp);

  factory RegExInputFormatter.withRegex(String regexString) {
    try {
      final regex = RegExp(regexString);
      return RegExInputFormatter._(regex);
    } catch (e) {
      // Something not right with regex string.
      assert(false, e.toString());
      return null;
    }
  }

  @override
  TextEditingValue formatEditUpdate(
      TextEditingValue oldValue, TextEditingValue newValue) {
    final oldValueValid = _isValid(oldValue.text);
    final newValueValid = _isValid(newValue.text);
    if (oldValueValid && !newValueValid) {
      return oldValue;
    }
    return newValue;
  }

  bool _isValid(String value) {
    try {
      final matches = _regExp.allMatches(value);
      for (Match match in matches) {
        if (match.start == 0 && match.end == value.length) {
          return true;
        }
      }
      return false;
    } catch (e) {
      // Invalid regex
      assert(false, e.toString());
      return true;
    }
  }
}

Use it in with your textfield

final _amountValidator = RegExInputFormatter.withRegex('^\$|^(0|([1-9][0-9]{0,}))(\\.[0-9]{0,})?\$');
...
TextField(
  inputFormatters: [_amountValidator],
  keyboardType: TextInputType.numberWithOptions(
    decimal: true,
     signed: false,
   ),
 )
Johnykutty
  • 12,091
  • 13
  • 59
  • 100
  • 2
    for restrict: RegExInputFormatter.withRegex('^[0-9]{0,6}(\\.[0-9]{0,2})?\$') – Adem Aygun Jan 09 '20 at 21:11
  • Does this work for locale's with commas instead of periods for the decimal character? – CodeGrue May 15 '20 at 20:43
  • I haven't tried that. But I believe you need to update the regex for that. – Johnykutty May 18 '20 at 17:25
  • @Johnykutty With all above requirements I want to allow minus numbers too. What changes are required in the Regex? – Dhaval Kansara Oct 26 '20 at 08:42
  • @DhavalKansara you could add `([-]{0,1})` to the begining of the regex. Something like '^\$|^(0|([1-9][0-9]{0,}))(\\.[0-9]{0,})?\$' PS: I haven't tried this in code, tried in https://www.regexpal.com – Johnykutty Oct 26 '20 at 10:39
9

I am using this code and it's giving different results , on some phones it shows only numbers and on others it shows dashes and other chars , so it depends on the launcher or something like that i guess, in iPhone i guess it will show the correct keyboard ( i have tried on iPhone 7s plus).

the inputFormatters will allow only numbers so you will get what you want.

   TextField(
     textAlign: TextAlign.start,
     keyboardType: TextInputType.numberWithOptions(decimal: true),
     inputFormatters: <TextInputFormatter>[
                          FilteringTextInputFormatter.digitsOnly
                       ],
   ),
Dung Ngo
  • 1,258
  • 1
  • 11
  • 24
redaDk
  • 261
  • 3
  • 5
4

I've been looking the answer to this problem too and found it after many attempts and hard work.

you can use this regex for decimal.

inputFormatters: [
        FilteringTextInputFormatter.allow(RegExp(r'^[0-9]+.?[0-9]*'))
      ],
  • Good!! It also works. – Sagar Zala Sep 13 '22 at 18:27
  • Great answer, one optimisation is use `\.` in the regex. e.g. `r'^[0-9]+\.?[0-9]*'` as `.` in regex could be any single character like `123:1`. – Neo Liu Apr 20 '23 at 05:33
  • Didn't spend a lot of time on this, but that RegExp let spaces and multiple periods through for me. Also, I wanted the decimal places to be optional. Found this in a Javascript RegExp answer that caught spaces and multiple periods: Try the following expression: ^\d+\.\d{0,2}$ If you want the decimal places to be optional, you can use the following: ^\d+(\.\d{1,2})?$ – user1544428 Aug 07 '23 at 19:05
3

Add the inputFormatters line:

 TextField(
     inputFormatters: <TextInputFormatter>[FilteringTextInputFormatter.allow(RegExp(r'^\d+\.?\d{0,2}'))],
          ...)
DeePanShu
  • 1,236
  • 10
  • 23
1

I have used this code in one of my Project and its working fine. I hope it will helps you.

TextField(
         decoration: InputDecoration(
         border: InputBorder.none,
         hintText: "Amount",
         hintStyle:
         TextStyle(color: Colors.grey, fontSize: 12.0),
         ),
         style: TextStyle(color: Colors.black, fontSize: 12.0),
         controller: _amountController[index],
         textInputAction: TextInputAction.done,
         keyboardType: TextInputType.numberWithOptions(decimal: true),)

enter image description here

Sunny
  • 3,134
  • 1
  • 17
  • 31
0

try this one for decimal

import 'package:flutter/services.dart';
...
keyboardType: TextInputType.numberWithOptions(decimal: true),
inputFormatters: [FilteringTextInputFormatter.allow(RegExp('[0-9.,]+')),],
onChanged: (value) => doubleVar = double.parse(value),

Also

RegExp('([0-9]+(.[0-9]+)?)') For allow digits and only one dot