如何在Flutter中创建数字输入框?

417

我无法找到在Flutter中创建一个只打开数字键盘并且仅接受数字输入的输入字段的方法。使用Flutter材料小部件是否可能实现这一点?一些GitHub讨论似乎表明这是一个支持的功能,但是我无法找到任何相关文档。


7
添加键盘类型 keyboardType: TextInputType.number,。 - Ishan Fernando
28个回答

688
您可以使用以下方式将keyboardType指定为TextField的数字:
keyboardType: TextInputType.number

检查一下我的 main.dart 文件。
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

void main() => runApp(new MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return new MaterialApp(
      home: new HomePage(),
      theme: new ThemeData(primarySwatch: Colors.blue),
    );
  }
}

class HomePage extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return new HomePageState();
  }
}

class HomePageState extends State<HomePage> {
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      backgroundColor: Colors.white,
      body: new Container(
        padding: const EdgeInsets.all(40.0),
        child: new Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            new TextField(
              decoration: new InputDecoration(labelText: "Enter your number"),
              keyboardType: TextInputType.number,
              inputFormatters: <TextInputFormatter>[
                FilteringTextInputFormatter.digitsOnly
              ], // Only numbers can be entered
            ),
          ],
        ),
      ),
    );
  }
}

enter image description here


26
但我可以把文字粘贴到那个区域,你有其他选择吗?@Rissmon Suresh - Thirumal Govindaraj
14
请确认需要翻译的内容是否正确: do not forget => import 'package:flutter/services.dart'; - Wilmer
1
允许输入点、空格和粘贴表情符号。 - agilob
21
这里也需要使用inputFormatters: [WhitelistingTextInputFormatter.digitsOnly],因为逗号和点仍然会被接受作为答案。 - Ravi Yadav
28
已弃用:inputFormatters: [WhitelistingTextInputFormatter.digitsOnly]。请改用:inputFormatters: [FilteringTextInputFormatter.digitsOnly]。 (注:这是关于Flutter框架中的输入格式化器的提示,建议开发者使用新的输入格式化器) - Eren
显示剩余5条评论

270
对于那些想要让TextFieldTextFormField只接受数字输入的人,可以尝试使用以下代码块:

适用于Flutter 1.20或更新版本

TextFormField(
  controller: _controller,
  keyboardType: TextInputType.number,
  inputFormatters: <TextInputFormatter>[
   // for below version 2 use this
 FilteringTextInputFormatter.allow(RegExp(r'[0-9]')), 
// for version 2 and greater youcan also use this
 FilteringTextInputFormatter.digitsOnly

  ],
  decoration: InputDecoration(
    labelText: "whatever you want",
    hintText: "whatever you want",
    icon: Icon(Icons.phone_iphone)
  )
)

对于早期版本的1.20

TextFormField(
    controller: _controller,
    keyboardType: TextInputType.number,
    inputFormatters: <TextInputFormatter>[
        WhitelistingTextInputFormatter.digitsOnly
    ],
    decoration: InputDecoration(
        labelText:"whatever you want", 
        hintText: "whatever you want",
        icon: Icon(Icons.phone_iphone)
    )
)

注意:使用FilteringTextInputFormatter时,需要导入services.dart

import 'package:flutter/services.dart';

8
欢迎使用此功能以避免用户粘贴非数字字符串(输入格式化程序),谢谢。 - Mariano Argañaraz
7
即使在Flutter_web中,这也能很好地运行。原因是在Flutter_web中,我们无法强制使用数字键盘,所以限制是自然的选择。感谢@BilalŞimşek。 - Abhilash Chandran
2
@Bensal,你也可以使用RegExp(r'[0-9]')来匹配controller.text。 - Bilal Şimşek
3
我使用Flutter 2.1.0,这仍然有效。 inputFormatters: <TextInputFormatter>[ WhitelistingTextInputFormatter.digitsOnly ], (该代码)用于输入文本格式化,并只允许输入数字。 - SilkeNL
4
在Flutter 2.2.2中,WhitelistingTextInputFormatter.digitsOnly已被弃用,代之以使用inputFormatters: <TextInputFormatter>[FilteringTextInputFormatter.digitsOnly]来仅允许输入数字(不允许逗号、空格或#)。 - M. A.
显示剩余5条评论

92

通过这个选项,你可以严格限制另一个字符而不包括数字。

 inputFormatters: [WhitelistingTextInputFormatter.digitsOnly],
 keyboardType: TextInputType.number,

要使用上述选项,您需要导入此内容

import 'package:flutter/services.dart';

使用这种选项,用户无法在文本字段中粘贴字符


3
如果我只想要小数和数字,如何将 "." 添加到格式化程序的白名单中? - shababhsiddique
6
@anoop4real 是的,我只是使用TextFormField( keyboardType: TextInputType.number, inputFormatters: [ FilteringTextInputFormatter.allow((RegExp("[.0-9]"))) ], ) 在正则表达式中有一个“.”。 - shababhsiddique
2
@shababhsiddique 它允许多个“.”。我想接受双精度数字。有什么想法吗? - Umesh Chakradhar
3
FilteringTextInputFormatter.allow(RegExp(r'^\d.?\d$')) - Nicolas
1
WhitelistingTextInputFormatter已经过时,请改用FilteringTextInputFormatter。https://dev59.com/vrfna4cB1Zd3GeqPztOI#70335837 - Didier
显示剩余3条评论

46

出现错误:局部变量num在声明之前不能被引用。 - kashlo
好的,变量名num不可用。需要更改名称。 - Günter Zöchbauer
1
从文档中得知:onError参数已被弃用并将被移除。您应该使用num.tryParse(string) ?? (...)来代替num.parse(string, (string) { ... })。 - kashlo

32

19

对于那些需要在文本字段中使用货币格式的人:

只能使用:, (逗号)和. (句点)

并屏蔽符号:- (连字号、减号或破折号)

以及:⌴(空格)

在您的TextField中,只需设置以下代码:

keyboardType: TextInputType.numberWithOptions(decimal: true),
inputFormatters: [BlacklistingTextInputFormatter(new RegExp('[\\-|\\ ]'))],

连字符和空格符号将仍然出现在键盘上,但将变成被阻止的状态。


1
你知道如何只允许一个逗号或句号吗? - HFranco
1
@HeddieFranco 阅读有关正则表达式的内容 https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Reference/Global_Objects/RegExp - Fellipe Sanches

18
如果你需要使用一个双倍的数字:
keyboardType: TextInputType.numberWithOptions(decimal: true),
inputFormatters: [FilteringTextInputFormatter.allow(RegExp('[0-9.,]')),],
onChanged: (value) => doubleVar = double.parse(value),

RegExp('[0-9.,]') 允许0到9之间的数字,以及逗号和点号。

RegExp('[0-9.,-]') 允许0到9之间的数字,以及逗号、点号和减号(用于负数)。

double.parse() 将字符串转换为双精度浮点数。

不要忘记需要导入以下内容:import 'package:flutter/services.dart';

您可以在this dartpad上检查和测试完整的演示。

如果您只想在字符串开头允许负号:

final RegExp _myPattern = RegExp(r'^-?[\d,.]*$');
(...)
TextInputFormatter.withFunction(
  (TextEditingValue oldValue, TextEditingValue newValue) {
    return _myPattern.hasMatch(newValue.text)
        ? newValue
         : oldValue;
   },
 ),

你可以在这个其他的dartpad上检查和测试完整的demo2

你的解决方案中缺少负数处理。 - undefined
@cabbi 谢谢你的评论。回答已更新 :-) - undefined
使用[0-9.,-],您可以在任何位置插入“-”符号(例如12-34.01)。应该是类似于:^-?[0-9.,],但是这个正则表达式并不按照我期望的方式工作。 - undefined
通常不应将FilteringTextInputFormatter与包含位置匹配符(^或$)的正则表达式一起使用。 https://api.flutter.dev/flutter/services/FilteringTextInputFormatter-class.html - undefined
1
@cabbi 我已经更新了答案,提供了一个选项,只允许在字符串开头使用负号。 - undefined

12
TextField小部件必须设置keyboardType: TextInputType.number,inputFormatters: <TextInputFormatter>[FilteringTextInputFormatter.digitsOnly],以仅接受数字作为输入。
     TextField(
            keyboardType: TextInputType.number,
            inputFormatters: <TextInputFormatter>[
              FilteringTextInputFormatter.digitsOnly
            ], // Only numbers can be entered
          ),

在DartPad中的示例

DartPad的截屏

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

    void main() => runApp(new MyApp());
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          home: HomePage(),
          theme: ThemeData(primarySwatch: Colors.blue),
        );
      }
    }
    
    class HomePage extends StatefulWidget {
      @override
      State<StatefulWidget> createState() {
        return HomePageState();
      }
    }
    
    class HomePageState extends State<HomePage> {
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          backgroundColor: Colors.white,
          body: Container(
              padding: const EdgeInsets.all(40.0),
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: <Widget>[
                  Text("This Input accepts Numbers only"),
                  SizedBox(height: 20),
                  TextField(
                    decoration: InputDecoration(
                      focusedBorder: OutlineInputBorder(
                        borderSide:
                            BorderSide(color: Colors.greenAccent, width: 5.0),
                      ),
                      enabledBorder: OutlineInputBorder(
                        borderSide: BorderSide(color: Colors.red, width: 5.0),
                      ),
                      hintText: 'Mobile Number',
                    ),
                    keyboardType: TextInputType.number,
                    inputFormatters: <TextInputFormatter>[
                      FilteringTextInputFormatter.digitsOnly
                    ], // Only numbers can be entered
                  ),
                  SizedBox(height: 20),
                  Text("You can test be Typing"),
                ],
              )),
        );
      }
    }

10

8
正如被接受的回答所述,指定 keyboardType 会触发数字键盘:
keyboardType: TextInputType.number

其他很好的回答指出,可以使用基于正则表达式的格式化程序,以允许仅输入整数:
inputFormatters: [
  FilteringTextInputFormatter.allow(RegExp(r'[0-9]')),
],

问题在于,这个正则表达式每次只匹配一个符号,所以无法通过这种方式限制小数点的数量(例如)。

此外,其他人也表明,如果需要对十进制数进行验证,可以使用TextFormField及其validator参数来实现:

new TextFormField(
    keyboardType: TextInputType.number, 
    validator: (v) => num.tryParse(v) == null ? "invalid number" : null, 
    ...

这样做的问题是它不能在交互式中实现,只能在表单提交时实现。


我想要只允许输入十进制数,而不是稍后进行验证。我的解决方案是编写一个利用int.tryParse的自定义格式化程序:

/// Allows only decimal numbers to be input.
class DecimalNumberFormatter extends TextInputFormatter {
  @override
  TextEditingValue formatEditUpdate(
      TextEditingValue oldValue, TextEditingValue newValue) {
    // Allow empty input and delegate formatting decision to `num.tryParse`.
    return newValue.text != '' && num.tryParse(newValue.text) == null
        ? oldValue
        : newValue;
  }
}

另一种方法是使用正则表达式作为定制格式化程序,这将适用于整个输入,而不仅仅是单个符号:

/// Allows only decimal numbers to be input. Limits decimal plates to 3.
class DecimalNumberFormatter extends TextInputFormatter {
  @override
  TextEditingValue formatEditUpdate(
      TextEditingValue oldValue, TextEditingValue newValue) {
    // Allow empty input.
    if (newValue.text == '') return newValue;

    // Regex: can start with zero or more digits, maybe followed by a decimal
    // point, followed by zero, one, two, or three digits.
    return RegExp('^\\d*\\.?\\d?\\d?\\d?\$').hasMatch(newValue.text)
        ? newValue
        : oldValue;
  }
}

这样,我还可以将小数点位数限制为3。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接