【问题标题】:Flutter TextField with currency format具有货币格式的 Flutter TextField
【发布时间】:2018-05-17 15:18:47
【问题描述】:

有一些方法可以在 TextField 中进行货币格式设置,以便用户输入已经实时格式化的值?

如上图所示,当用户输入格式时,会更新已格式化的值。

[更新]

我刚刚发现这个库使它像一个魅力一样工作: https://pub.dartlang.org/packages/flutter_masked_text

【问题讨论】:

标签: dart flutter


【解决方案1】:

设置自定义货币掩码的简单解决方案是使用 flutter_masked_text 包:

1 - 首先,您需要将此包添加到包的 pubspec.yaml 文件中:

dependencies:
  flutter_masked_text: ^0.7.0

2 - 之后,使用命令行安装包(如下所示),或者使用图形界面,如果您使用的是 IntelliJ IDEA,只需单击“Packages get”按钮。

flutter packages get

3 - 现在在你的 Dart 代码中,导入它...

import 'package:flutter_masked_text/flutter_masked_text.dart';

4 - 最后,将 TextField 控制器代码从“TextEditingController”更改为“MoneyMaskedTextController”:

  //final lowPrice = TextEditingController(); //before
  final lowPrice = MoneyMaskedTextController(decimalSeparator: '.', thousandSeparator: ','); //after

【讨论】:

  • 是的,@Fellipe Sanches,正如我在顶部所说的那样更好,我会标记你的回复,谢谢。
  • 包有问题,光标跳来跳去,在某些设备上退格不能正常工作
  • MoneyMaskedTextController 也有问题,每当我键入光标时,它就会跳到文件的开头。任何想法如何解决这个问题?
  • final rendaMensalController = MoneyMaskedTextController(decimalSeparator: '.', thousandSeparator: ',', leftSymbol: 'R\$'); 在左侧显示硬币类型。
【解决方案2】:

[此代码不适用于所有情况]

我只是以这种方式工作,分享以防有人需要:

文本字段

TextFormField(  
    //validator: ,  
    controller: controllerValor,  
    inputFormatters: [  
        WhitelistingTextInputFormatter.digitsOnly,
        // Fit the validating format.
        //fazer o formater para dinheiro
        CurrencyInputFormatter()
    ],
    keyboardType: TextInputType.number, ...  

TextInputFormatter

class CurrencyInputFormatter extends TextInputFormatter {

    TextEditingValue formatEditUpdate(TextEditingValue oldValue, TextEditingValue newValue) {

        if(newValue.selection.baseOffset == 0){
            print(true);
            return newValue;
        }

        double value = double.parse(newValue.text);

        final formatter = NumberFormat.simpleCurrency(locale: "pt_Br");

        String newText = formatter.format(value/100);

        return newValue.copyWith(
            text: newText,
            selection: new TextSelection.collapsed(offset: newText.length));
    }
}

这是代码的结果:

【讨论】:

  • 你好,NumberFormat() 类是从哪里来的?
  • 你好,来自这个库pub.dartlang.org/packages/intl
  • 你好@JorgeVieira,代码可以工作,但有一点问题,零的输入不起作用。例如我无法输入数字“500”,最后两个零不输入。
  • 注意到TextInputFormatter 来自import 'package:flutter/services.dart';
  • 非常好用,可以用其他方式使用。我正在使用它来格式化不同类型的字段。
【解决方案3】:


使用intl 包。完整代码:

import 'package:intl/intl.dart';

class _HomePageState extends State<HomePage> {
  final _controller = TextEditingController();
  static const _locale = 'en';
  String _formatNumber(String s) => NumberFormat.decimalPattern(_locale).format(int.parse(s));
  String get _currency => NumberFormat.compactSimpleCurrency(locale: _locale).currencySymbol;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: TextField(
        controller: _controller,
        decoration: InputDecoration(prefixText: _currency),
        keyboardType: TextInputType.number,
        onChanged: (string) {
          string = '${_formatNumber(string.replaceAll(',', ''))}';
          _controller.value = TextEditingValue(
            text: string,
            selection: TextSelection.collapsed(offset: string.length),
          );
        },
      ),
    );
  }
}

【讨论】:

  • 你救了我。我遇到了一个问题,因为我将 onChanged 回调中的字符串直接分配给 control.text ..这会将光标路径冻结在文本字段的开头..因此将推算文本反转..我也在使用controller.text.length 来偏移选择而不是 onChanged String 。非常感谢。
  • 如何用点改变逗号?
  • @RohmatulLaily 逗号来自compactSimpleCurrency,如果您的语言环境允许点,则会自动添加。
  • 这适用于整数,但不适用于十进制值,例如:1,234.90。它导致 TextField 停止在 1,234。这种情况有什么解决方法吗?
【解决方案4】:

这个库非常适合我:

https://pub.dev/packages/currency_text_input_formatter

...
inputFormatters: [
  CurrencyTextInputFormatter(
    decimalDigits: 0,
    locale: 'ru',
  )
]
...

【讨论】:

    【解决方案5】:

    更新了@AndréLuis 的代码以限制位数(maxDigits),感谢分享。

    import 'package:flutter/services.dart';
    import 'package:intl/intl.dart';
    
    class CurrencyPtBrInputFormatter extends TextInputFormatter {
      CurrencyPtBrInputFormatter({this.maxDigits});
      final int maxDigits;
    
      TextEditingValue formatEditUpdate(
          TextEditingValue oldValue, TextEditingValue newValue) {
    
        if (newValue.selection.baseOffset == 0) {
          return newValue;
        }
    
        if (maxDigits != null && newValue.selection.baseOffset > maxDigits) {
          return oldValue;
        }
    
        double value = double.parse(newValue.text);
        final formatter = new NumberFormat("#,##0.00", "pt_BR");
        String newText = "R\$ " + formatter.format(value / 100);
        return newValue.copyWith(
            text: newText,
            selection: new TextSelection.collapsed(offset: newText.length));
      }
    }
    

    对 TextFormField 使用下面的代码,我还将值解析为 double,使用 RegExp 删除非数字字符。

    TextFormField(
      maxLines: 1,
      keyboardType: TextInputType.number,
      inputFormatters: [
        WhitelistingTextInputFormatter.digitsOnly,
        CurrencyPtBrInputFormatter(maxDigits: 8),
      ],
      onSaved: (value) {
        String _onlyDigits = value.replaceAll(RegExp('[^0-9]'), "");
        double _doubleValue = double.parse(_onlyDigits) / 100;
        return _valor = _doubleValue;
      },
    );
    

    【讨论】:

      【解决方案6】:

      为了使代码更简洁,可以将隐藏的值作为方法包含在 Formatter 类中。因此,当值发生更改时,您将能够调用它并简化代码。

      Widget build(BuildContext context) {
          var maskFormatter = new CurrencyPtBrFormatter(maxDigits: 12);
          return Scaffold(
              body: SingleChildScrollView(
                  controller: _scrollController,
                  child: Column(
                    children: <Widget>[
                      TextField(
                        keyboardType: TextInputType.number,
                        inputFormatters: [
                          WhitelistingTextInputFormatter.digitsOnly,
                          maskFormatter,
                        ],
                        controller: _yourController,
                        onChanged: (value) {
                          print(maskFormatter.getUnmaskedDouble()); // here the umasked value
                        },
                        onEditingComplete: () {
                          mudarFocoCampo(context, _estoqueFocus, _codigoFocus);
                        },
                      )
                    ],
                  )));
        }
      

      这里是带有 umasked 方法的完整格式化程序。

      import 'package:flutter/services.dart';
      import 'package:intl/intl.dart';
      class CurrencyPtBrFormatter extends TextInputFormatter {
        CurrencyPtBrFormatter({this.maxDigits});
        final int maxDigits;
        double _uMaskValue;
        TextEditingValue formatEditUpdate(
            TextEditingValue oldValue, TextEditingValue newValue) {
          if (newValue.selection.baseOffset == 0) {
            return newValue;
          }
          if (maxDigits != null && newValue.selection.baseOffset > maxDigits) {
            return oldValue;
          }
          double value = double.parse(newValue.text);
          final formatter = new NumberFormat("#,##0.00", "pt_BR");
          String newText = "R\$ " + formatter.format(value / 100);
          //setting the umasked value
          _uMaskValue = value / 100;
          return newValue.copyWith(
              text: newText,
              selection: new TextSelection.collapsed(offset: newText.length));
        }
        //here the method
        double getUnmaskedDouble() {
          return _uMaskValue;
        }
      }
      

      【讨论】:

        猜你喜欢
        • 2022-11-09
        • 2018-07-18
        • 2012-01-29
        • 1970-01-01
        • 2015-10-24
        • 2012-01-22
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多