flutter 输入中只允许使用两位小数?

问题描述 投票:0回答:16

我只想在颤振输入中小数点后两位数字。用户不能在小数点后添加超过两位数字。

dart flutter flutter-layout
16个回答
64
投票

给你! 希望有帮助:)

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;
  }
}

46
投票

这是一个适合我的解决方案

TextFormField(
    inputFormatters: [
        WhitelistingTextInputFormatter(RegExp(r'^\d+\.?\d{0,2}')),
    ],
)

如果您想允许输入(.21)或(.25)

这是一个解决方案-

TextFormField(
    inputFormatters: [
        WhitelistingTextInputFormatter(RegExp(r'^(\d+)?\.?\d{0,2}')),
    ],
)

28
投票

Flutter 版本 v1.20.0-1.0 之后。使用

TextFormField(
  keyboardType: TextInputType.numberWithOptions(decimal: true),
  inputFormatters: [
    FilteringTextInputFormatter.allow(RegExp(r'^\d+\.?\d{0,2}')),
  ],
),

22
投票

对于 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}')),
  ],

它允许小数,如

1.
.89
8.99


9
投票

使用正则表达式的 DecimalTextInputFormatter 的较短版本:

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;
  }
}

6
投票

Dart SDK版本:2.13.4(稳定) Flutter 2.2.3 • 通道稳定

我于 2021 年 7 月 25 日写下这个答案,建议一个更简单的解决方案,仅使用内置 TextField 的

inputFormatters

我试图向大家保证,该字段不会接受超过 2 的浮点数(已接受:12.25 与未接受:65.536)。而且,它不接受多个点,只接受一个点(接受:12.25 vs 不接受:1.1.11、1.11、.1.1、1.1.1.1,无论如何..)。

考虑其他答案的区别在于,下面的代码不会接受

.1
,它以编程方式等于
0.1
,这实际上对用户更友好。而且它很简单,对我们来说很好看。您只需将以下代码复制并粘贴到
inputFormatters: []
即可。

如果你想同时接受

0.1
.1
(不仅仅是
0.1
),你可以直接注释掉
FilteringTextInputFormatter.allow(RegExp(r'^\d+\.?\d*'))

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

当您想更改最大小数点时,您可以更改以下行中的

N
值:

inputFormatters: [ FilteringTextInputFormatter.allow(RegExp(r'^(\d+)?\.?\d{0,N}')), FilteringTextInputFormatter.allow(RegExp(r'^\d+\.?\d*')), ]

第一个示例显示了您希望将小数点限制为 2 的情况,并且 N 值精确控制该限制。您可以在自己的代码中尝试[:

感谢所有其他答案,希望这个答案可以帮助未来的流浪者!祝你有美好的一天[:


4
投票

也许这是一个更简单的解决方案

inputFormatters: [
            FilteringTextInputFormatter.allow(RegExp(r'(^\d*\.?\d{0,2})'))
          ]

2
投票

也许对你来说有点晚了,但我也进步了一点:

  1. 仅允许 1
    .
  2. 允许负面
  3. 在开头加上负号

希望有帮助;)

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);
  }
}

(别忘了导入之前的类)

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),
      ],
    );
  }
}

1
投票

我扩展了功能......我希望你会发现它有用。请告诉我您是否可以进一步改进。

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;
}
}

1
投票

如果您正在寻找正则表达式来处理带有 2 位小数的逗号和点,请尝试此版本:

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})')),
              ],
            );

0
投票

@AjayKumar 的答案允许将文本输入限制为所需的小数位。但我的要求是避免键盘上除数字和点之外的其他字符。所以,我更新了 @AjayKumar 的上述答案

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;

} }


0
投票

并避免不必要的零...请调试此代码。

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;
  }
}

0
投票

我认为这是对我来说最简单且唯一的工作方式:

inputFormatters: [ LengthLimitingTextInputFormatter(2), ]


0
投票

对于 Flutter 中的 TextFeild ,具有 小数点前和小数点后长度验证类。

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;
  }
}    

在 TextField 中, 前任。小数点前 9 位数字和小数点后 2 位数字允许的代码如下。

inputFormatters: [ FilteringTextInputFormatter.allow(RegExp(r'^\d+\.?\d{0,2}')),
                   DecimalTextInputFormatter(decimalRange: 2, beforeDecimalRange: 9)
                 ],
keyboardType: TextInputType.numberWithOptions(decimal: true),

0
投票

这对我有用 (2022 年 2 月)

将文本限制为 2 个小数点,并且只有 1 个“.” (句号)

如果用户手动删除“.”之前的数字,

0 将自动添加到号码的开头

PS:对答案稍作编辑

文本表单字段

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,
    );
  }
}

0
投票
 keyboardType: TextInputType.numberWithOptions(decimal: true),
 inputFormatters: [LengthLimitingTextInputFormatter(5)],

这对我有用。

© www.soinside.com 2019 - 2024. All rights reserved.