I want only two digits after the decimal point in the flutter input.User can't add more than two digits after the decimal point.
-
You can use `TextEditingController` to listen for the inputs and manage your logic there. – CopsOnRoad Jan 31 '19 at 07:01
-
So there is no possiblity of inputformatter. Eg.inputFormatters: (keyboardType == TextInputType.number) ? [WhitelistingTextInputFormatter.digitsOnly] : [], – Hitesh Danidhariya Jan 31 '19 at 07:19
-
As far as I can say, no they won't help you, they can only give you options to choose specific type of keyboard. – CopsOnRoad Jan 31 '19 at 07:21
-
Thanks you so much,don't know why this question got -2 points. – Hitesh Danidhariya Jan 31 '19 at 07:28
-
Probably because you didn't show any code you tried, and no one is going to write a solution for you from scratch. – CopsOnRoad Jan 31 '19 at 07:54
-
You should update the answer, I found a simpler one. – theboringdeveloper Jun 28 '20 at 18:59
16 Answers
Here you go! Hope it helps :)
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'dart:math' as math;
void main() {
runApp(new MaterialApp(home: new MyApp()));
}
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Flutter"),
),
body: Form(
child: ListView(
children: <Widget>[
TextFormField(
inputFormatters: [DecimalTextInputFormatter(decimalRange: 2)],
keyboardType: TextInputType.numberWithOptions(decimal: true),
)
],
),
),
);
}
}
class DecimalTextInputFormatter extends TextInputFormatter {
DecimalTextInputFormatter({this.decimalRange})
: assert(decimalRange == null || decimalRange > 0);
final int decimalRange;
@override
TextEditingValue formatEditUpdate(
TextEditingValue oldValue, // unused.
TextEditingValue newValue,
) {
TextSelection newSelection = newValue.selection;
String truncated = newValue.text;
if (decimalRange != null) {
String value = newValue.text;
if (value.contains(".") &&
value.substring(value.indexOf(".") + 1).length > decimalRange) {
truncated = oldValue.text;
newSelection = oldValue.selection;
} else if (value == ".") {
truncated = "0.";
newSelection = newValue.selection.copyWith(
baseOffset: math.min(truncated.length, truncated.length + 1),
extentOffset: math.min(truncated.length, truncated.length + 1),
);
}
return TextEditingValue(
text: truncated,
selection: newSelection,
composing: TextRange.empty,
);
}
return newValue;
}
}

- 15,250
- 14
- 54
- 53
-
1@AjayKumar the code 'math.min(truncated.length, truncated.length + 1)' looks quite redundant. – thanhbinh84 Mar 30 '20 at 09:12
-
3Problem with this is forcing a '.' doesn't support locales that swap periods and commas. – CodeGrue May 15 '20 at 20:30
-
@AjayKumar Thanks, worked for me. On some keyboards it is necessary to click the point to add a minus. In this class, you can enter minus after entering all values. I will add if I check this out. Thanks again. – Muhammet Ömer Sep 09 '20 at 10:32
-
If user add more numbers after decimal points removing not work until reach to first two numbers. – BeHappy Nov 12 '20 at 19:12
-
Hey, this won't work if the device uses a Locale that uses the comma `,` as decimal separator, like in Spanish – Roc Boronat Jun 30 '21 at 09:12
Here is a solution which works for me
TextFormField(
inputFormatters: [
WhitelistingTextInputFormatter(RegExp(r'^\d+\.?\d{0,2}')),
],
)
If you want to allow input like (.21) or (.25)
Here is a solution-
TextFormField(
inputFormatters: [
WhitelistingTextInputFormatter(RegExp(r'^(\d+)?\.?\d{0,2}')),
],
)

- 1,429
- 13
- 17
-
-
1How to restrict the digits only for 4 before decimal @theboringdeveloper – hemandroid Mar 31 '21 at 09:24
-
14Simplest solution, one thing to add, `WhitelistingTextInputFormatter` is deprecated use `FilteringTextInputFormatter.allow(RegExp(r'^\d+\.?\d{0,2}'))` instead. – joe_inz Sep 27 '21 at 14:39
-
This worked for me, note that services has to be imported with `import 'package:flutter/services.dart';` – nck Nov 01 '22 at 19:54
after Flutter Version v1.20.0-1.0. use
TextFormField(
keyboardType: TextInputType.numberWithOptions(decimal: true),
inputFormatters: [
FilteringTextInputFormatter.allow(RegExp(r'^\d+\.?\d{0,2}')),
],
),

- 3,793
- 1
- 25
- 37
-
How to restrict the digits 4 digits between 0-9 before decimal @Nuqo – hemandroid Mar 31 '21 at 09:25
For Dart 2.00+
TextFormField(
keyboardType: TextInputType.numberWithOptions(decimal: true),
inputFormatters: [
// Allow Decimal Number With Precision of 2 Only
FilteringTextInputFormatter.allow(RegExp(r'^\d*\.?\d{0,2}')),
],
It allows decimals like 1.
, .89
, 8.99

- 1,407
- 15
- 12
-
1
-
2
-
1You can change the min and max number of decimal places by changing the number inside the parenthesis – Muheeb Mehraj Mar 06 '23 at 17:32
-
I am removing commas like this, in conjunction with the other formatter: ```TextInputFormatter.withFunction( (oldValue, newValue) => newValue.copyWith(text: newValue.text.replaceAll(',', '.'), ),)``` – Mário Meyrelles Mar 29 '23 at 23:17
A shorter Version of DecimalTextInputFormatter using Regexp:
class DecimalTextInputFormatter extends TextInputFormatter {
DecimalTextInputFormatter({int decimalRange, bool activatedNegativeValues})
: assert(decimalRange == null || decimalRange >= 0,
'DecimalTextInputFormatter declaretion error') {
String dp = (decimalRange != null && decimalRange > 0) ? "([.][0-9]{0,$decimalRange}){0,1}" : "";
String num = "[0-9]*$dp";
if(activatedNegativeValues) {
_exp = new RegExp("^((((-){0,1})|((-){0,1}[0-9]$num))){0,1}\$");
}
else {
_exp = new RegExp("^($num){0,1}\$");
}
}
RegExp _exp;
@override
TextEditingValue formatEditUpdate(
TextEditingValue oldValue,
TextEditingValue newValue,
) {
if(_exp.hasMatch(newValue.text)){
return newValue;
}
return oldValue;
}
}

- 316
- 3
- 4
-
Thanks, this code also ignores letters and symbols, leaving only digits and a dot. – Andrey Gordeev Feb 11 '20 at 11:07
-
Dart SDK version: 2.13.4 (stable) Flutter 2.2.3 • channel stable
i'm writing this answer on July 25, 2021, suggesting a little bit simpler solution, only using built-in TextField's inputFormatters
.
i'm trying to ensure all of you, that the field won't accept floating point longer than 2(accepted: 12.25 vs notAccepted: 65.536). And also, it won't accept multiple dots, only accept a single dot(accepted: 12.25 vs notAccepted: 1.1.11, 1.11, .1.1, 1.1.1.1, whatsoever..).
The difference considering the other answers is that the code below won't accept .1
which is equal to 0.1
programmatically, which is actually way more user-friendly. And it is simple, nice to look at for us. You can just copy and paste the code below into inputFormatters: []
.
If you want to accept both 0.1
and .1
(not only 0.1
), you can just comment out FilteringTextInputFormatter.allow(RegExp(r'^\d+\.?\d*'))
!
inputFormatters: [ FilteringTextInputFormatter.allow(RegExp(r'^(\d+)?\.?\d{0,2}')), FilteringTextInputFormatter.allow(RegExp(r'^\d+\.?\d*')), ]
When you want to change the maximum decimal point, you can change the N
value in the line below:
inputFormatters: [ FilteringTextInputFormatter.allow(RegExp(r'^(\d+)?\.?\d{0,N}')), FilteringTextInputFormatter.allow(RegExp(r'^\d+\.?\d*')), ]
First example shows the case in which you want to limit decimal point to 2, and the N value exactly controls the limit. You might try within your own code [:
Appreciate all the other answers, hope this answer might help future wanderers! Have a wonderful day [:

- 1,851
- 3
- 14
- 24
May be this is a simpler solution
inputFormatters: [
FilteringTextInputFormatter.allow(RegExp(r'(^\d*\.?\d{0,2})'))
]

- 81
- 4
-
can you specify what's better regarding the other answer that use the regex? – Gianmarco Nov 18 '20 at 17:48
-
Maybe a little late for you, but I also improved a little:
- Allow only 1
.
- Allow negative
- Place negative sign on beginning
Hope it helps ;)
import 'package:flutter/services.dart';
class NumberTextInputFormatter extends TextInputFormatter {
NumberTextInputFormatter({this.decimalRange}) : assert(decimalRange == null || decimalRange > 0);
final int decimalRange;
@override
TextEditingValue formatEditUpdate(TextEditingValue oldValue, TextEditingValue newValue) {
TextEditingValue _newValue = this.sanitize(newValue);
String text = _newValue.text;
if (decimalRange == null) {
return _newValue;
}
if (text == '.') {
return TextEditingValue(
text: '0.',
selection: _newValue.selection.copyWith(baseOffset: 2, extentOffset: 2),
composing: TextRange.empty,
);
}
return this.isValid(text) ? _newValue : oldValue;
}
bool isValid(String text) {
int dots = '.'.allMatches(text).length;
if (dots == 0) {
return true;
}
if (dots > 1) {
return false;
}
return text.substring(text.indexOf('.') + 1).length <= decimalRange;
}
TextEditingValue sanitize(TextEditingValue value) {
if (false == value.text.contains('-')) {
return value;
}
String text = '-' + value.text.replaceAll('-', '');
return TextEditingValue(text: text, selection: value.selection, composing: TextRange.empty);
}
}
and (don't forget to import the previous class)
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
class NumberFormField extends StatelessWidget {
final InputDecoration decoration;
final TextEditingController controller;
final int decimalRange;
const NumberFormField({Key key, this.decoration, this.controller, this.decimalRange}) :super(key: key);
@override
Widget build(BuildContext context) {
return TextFormField(
decoration: this.decoration,
controller: this.controller,
keyboardType: TextInputType.numberWithOptions(decimal: true),
inputFormatters: [
WhitelistingTextInputFormatter(RegExp(r'[\d+\-\.]')),
NumberTextInputFormatter(decimalRange: this.decimalRange),
],
);
}
}

- 589
- 3
- 9
I extended the functionalities ... I hope you can find it useful. Tell me if you can improve even more please.
import 'package:flutter/services.dart';
import 'dart:math' as math;
class DecimalTextInputFormatter extends TextInputFormatter {
DecimalTextInputFormatter({this.decimalRange, this.activatedNegativeValues})
: assert(decimalRange == null || decimalRange >= 0,
'DecimalTextInputFormatter declaretion error');
final int decimalRange;
final bool activatedNegativeValues;
@override
TextEditingValue formatEditUpdate(
TextEditingValue oldValue, // unused.
TextEditingValue newValue,
) {
TextSelection newSelection = newValue.selection;
String truncated = newValue.text;
if (newValue.text.contains(' ')) {
return oldValue;
}
if (newValue.text.isEmpty) {
return newValue;
} else if (double.tryParse(newValue.text) == null &&
!(newValue.text.length == 1 &&
(activatedNegativeValues == true ||
activatedNegativeValues == null) &&
newValue.text == '-')) {
return oldValue;
}
if (activatedNegativeValues == false &&
double.tryParse(newValue.text) < 0) {
return oldValue;
}
if (decimalRange != null) {
String value = newValue.text;
if (decimalRange == 0 && value.contains(".")) {
truncated = oldValue.text;
newSelection = oldValue.selection;
}
if (value.contains(".") &&
value.substring(value.indexOf(".") + 1).length > decimalRange) {
truncated = oldValue.text;
newSelection = oldValue.selection;
} else if (value == ".") {
truncated = "0.";
newSelection = newValue.selection.copyWith(
baseOffset: math.min(truncated.length, truncated.length + 1),
extentOffset: math.min(truncated.length, truncated.length + 1),
);
}
return TextEditingValue(
text: truncated,
selection: newSelection,
composing: TextRange.empty,
);
}
return newValue;
}
}

- 837
- 6
- 11
-
the solutions here are pretty good. i think that it would make it even better if the comma is included when formatting in the thousands. – chitgoks Jun 10 '20 at 13:24
-
Hi Sir! Its possible to add a Number format to your code with decimalRange max 2? I want to achieve this: "100.25" "1,000.25" "10,000.25" – Nikssj_ Nov 02 '20 at 04:52
If you are looking for a regexp to handle comma and dot with 2 decimals try this version:
TextFormField(
keyboardType: const TextInputType.numberWithOptions(decimal: true),
decoration: textFieldDecoration("Price with only 2 decimals and handling comma"),
inputFormatters: [
FilteringTextInputFormatter.allow(RegExp(r'(^\d*[\.\,]?\d{0,2})')),
],
);

- 587
- 4
- 16
-
You can safely remove . and , escape. `RegExp(r'(^\d*[.,]?\d{0,2})')` instead of `RegExp(r'(^\d*[\.\,]?\d{0,2})')` – ivan-capk-me Jul 31 '23 at 12:16
The answer by @AjayKumar allows to limit text input to required decimal places.But my requirement was to avoid another character from keyboard except the number and a dot.So, I updated @AjayKumar's above answer
import 'package:flutter/services.dart';
import 'dart:math' as math;
class DecimalTextInputFormatter extends TextInputFormatter {
DecimalTextInputFormatter({this.decimalRange})
: assert(decimalRange == null || decimalRange > 0);
final int decimalRange;
@override
TextEditingValue formatEditUpdate(
TextEditingValue oldValue, // unused.
TextEditingValue newValue,
) {
TextSelection newSelection = newValue.selection;
String truncated = newValue.text;
if (decimalRange != null) {
String value = newValue.text;
if (value.contains(',') ||
value.contains('-') ||
value.contains(' ') ||
value.contains('..')) {
truncated = oldValue.text;
newSelection = oldValue.selection;
} else if (value.contains(".") &&
value.substring(value.indexOf(".") + 1).length > decimalRange) {
truncated = oldValue.text;
newSelection = oldValue.selection;
} else if (value == ".") {
truncated = "0.";
newSelection = newValue.selection.copyWith(
baseOffset: math.min(truncated.length, truncated.length + 1),
extentOffset: math.min(truncated.length, truncated.length + 1),
);
}
return TextEditingValue(
text: truncated,
selection: newSelection,
composing: TextRange.empty,
);
}
return newValue;
} }

- 766
- 6
- 14
And avoiding non necessary zeros... Please debug this code.
import 'dart:math' as math;
import 'package:flutter/services.dart';
class DecimalTextInputFormatter extends TextInputFormatter {
DecimalTextInputFormatter({this.decimalRange, this.activatedNegativeValues})
: assert(decimalRange == null || decimalRange >= 0,
'DecimalTextInputFormatter declaretion error');
final int decimalRange;
final bool activatedNegativeValues;
@override
TextEditingValue formatEditUpdate(
TextEditingValue oldValue, // unused.
TextEditingValue newValue,
) {
TextSelection newSelection = newValue.selection;
String truncated = newValue.text;
if (newValue.text.contains(' ')) {
return oldValue;
}
if (newValue.text.isEmpty) {
return newValue;
} else if (double.tryParse(newValue.text) == null &&
!(newValue.text.length == 1 &&
(activatedNegativeValues == true ||
activatedNegativeValues == null) &&
newValue.text == '-')) {
return oldValue;
}
if (activatedNegativeValues == false &&
double.tryParse(newValue.text) < 0) {
return oldValue;
}
if ((double.tryParse(oldValue.text) == 0 && !newValue.text.contains('.'))) {
if (newValue.text.length >= oldValue.text.length) {
return oldValue;
}
}
if (decimalRange != null) {
String value = newValue.text;
if (decimalRange == 0 && value.contains(".")) {
truncated = oldValue.text;
newSelection = oldValue.selection;
}
if (value.contains(".") &&
value.substring(value.indexOf(".") + 1).length > decimalRange) {
truncated = oldValue.text;
newSelection = oldValue.selection;
} else if (value == ".") {
truncated = "0.";
newSelection = newValue.selection.copyWith(
baseOffset: math.min(truncated.length, truncated.length + 1),
extentOffset: math.min(truncated.length, truncated.length + 1),
);
}
return TextEditingValue(
text: truncated,
selection: newSelection,
composing: TextRange.empty,
);
}
return newValue;
}
}

- 837
- 6
- 11
For TextFeild in Flutter with Before decimal & After decimal length validation class.
import 'package:flutter/cupertino.dart';
import 'package:flutter/services.dart';
import 'dart:math' as math;
class DecimalTextInputFormatter extends TextInputFormatter {
DecimalTextInputFormatter({this.decimalRange,this.beforeDecimalRange})
: assert(decimalRange == null || decimalRange > 0 || beforeDecimalRange == null || beforeDecimalRange > 0 );
final int decimalRange;
final int beforeDecimalRange;
@override
TextEditingValue formatEditUpdate(
TextEditingValue oldValue, // unused.
TextEditingValue newValue,
) {
TextSelection newSelection = newValue.selection;
String truncated = newValue.text;
String value;
if(beforeDecimalRange != null){
value = newValue.text;
if(value.contains(".")){
if(value.split(".")[0].length > beforeDecimalRange){
truncated = oldValue.text;
newSelection = oldValue.selection;
}
}else{
if(value.length > beforeDecimalRange){
truncated = oldValue.text;
newSelection = oldValue.selection;
}
}
}
if (decimalRange != null) {
value = newValue.text;
if (value.contains(".") &&
value.substring(value.indexOf(".") + 1).length > decimalRange) {
truncated = oldValue.text;
newSelection = oldValue.selection;
} else if (value == ".") {
truncated = "0.";
newSelection = newValue.selection.copyWith(
baseOffset: math.min(truncated.length, truncated.length + 1),
extentOffset: math.min(truncated.length, truncated.length + 1),
);
}
return TextEditingValue(
text: truncated,
selection: newSelection,
composing: TextRange.empty,
);
}
return newValue;
}
}
In TextFeild , Ex. Before decimal 9 digit & after Decimal 2 digit allowed code below.
inputFormatters: [ FilteringTextInputFormatter.allow(RegExp(r'^\d+\.?\d{0,2}')),
DecimalTextInputFormatter(decimalRange: 2, beforeDecimalRange: 9)
],
keyboardType: TextInputType.numberWithOptions(decimal: true),

- 11
- 3
This worked for me (Feb/2022)
Restricts the text to 2 decimal point and have only 1 '.' (period)
0 will be automatically added to the start of the number if user go and manually remove the digit before the '.'
PS: A Slight edit to the answer
TextFormField
TextFormField(
autofocus: false,
keyboardType: TextInputType.number,
controller: controller,
inputFormatters: [
DecimalTextInputFormatter(decimalRange: 2),
],
validator: (value) {
if (value == null || value.isEmpty) {
return 'Please add amount.';
}
return null;
},
DecimalTextInputFormatter
import 'package:flutter/services.dart';
import 'dart:math' as math;
class DecimalTextInputFormatter extends TextInputFormatter {
DecimalTextInputFormatter({required this.decimalRange})
: assert(decimalRange > 0);
final int decimalRange;
@override
TextEditingValue formatEditUpdate(
TextEditingValue oldValue,
TextEditingValue newValue,
) {
TextSelection newSelection = newValue.selection;
String truncated = newValue.text;
String value = newValue.text;
if (value.contains(".") &&
value.substring(value.indexOf(".") + 1).length > decimalRange) {
truncated = oldValue.text;
newSelection = oldValue.selection;
} else if (value == ".") {
truncated = "0.";
newSelection = newValue.selection.copyWith(
baseOffset: math.min(truncated.length, truncated.length + 1),
extentOffset: math.min(truncated.length, truncated.length + 1),
);
} else if (value.contains(".")) {
String tempValue = value.substring(value.indexOf(".") + 1);
if (tempValue.contains(".")) {
truncated = oldValue.text;
newSelection = oldValue.selection;
}
if (value.indexOf(".") == 0) {
truncated = "0" + truncated;
newSelection = newValue.selection.copyWith(
baseOffset: math.min(truncated.length, truncated.length + 1),
extentOffset: math.min(truncated.length, truncated.length + 1),
);
}
}
if (value.contains(" ") || value.contains("-")) {
truncated = oldValue.text;
newSelection = oldValue.selection;
}
return TextEditingValue(
text: truncated,
selection: newSelection,
composing: TextRange.empty,
);
}
}

- 1
- 2
keyboardType: TextInputType.numberWithOptions(decimal: true),
inputFormatters: [LengthLimitingTextInputFormatter(5)],
This works for me.

- 445
- 5
- 11
I think this is the most simplest and only way working for me:
inputFormatters: [ LengthLimitingTextInputFormatter(2), ]

- 606
- 5
- 19
-
3The question was to restrict user input of more than two "decimal digits". The given code restricts input of more than 2 characters. Totally different things. – Abhimanyu Apr 04 '21 at 14:32