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

How to create number input field in Flutter?

我找不到在 Flutter 中创建可以打开数字键盘的输入字段的方法。这对 Flutter material 小部件来说可能吗?一些 github 讨论似乎表明这是一项受支持的功能,但我找不到任何关于它的文档。

设置键盘和验证器

String numberValidator(String value) {
  if(value == null) {
    return null;
  }
  final n = num.tryParse(value);
  if(n == null) {
    return '"$value" is not a valid number';
  }
  return null;
}

new TextFormField(
    keyboardType: TextInputType.number, 
    validator: numberValidator, 
    textAlign: TextAlign.right
    ...

您可以使用以下方法将号码指定为 keyboardType for the 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
          ),
        ],
      )),
    );
  }
}

您可以使用 keyboardType 参数轻松更改输入类型 你有很多可能性检查文档 TextInputType 所以您可以使用数字或 phone 值

 new TextField(keyboardType: TextInputType.number)

你可以试试这个:

TextFormField(
     keyboardType: TextInputType.number,
     decoration: InputDecoration(
              prefixIcon: Text("Enter your number: ")
     ),
     initialValue: "5",
     onSaved: (input) => _value = num.tryParse(input),
),

对于那些正在寻找 TextFieldTextFormField 只接受数字作为输入的人,试试这个代码块:

对于 flutter 1.20 或更新版本

TextFormField(
  controller: _controller,
  keyboardType: TextInputType.number,
  inputFormatters: <TextInputFormatter>[
    FilteringTextInputFormatter.allow(RegExp(r'[0-9]')),
  ],
  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)
    )
)

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

仅使用:,(逗号) 和。 (句点)

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

以及:⌴(空白space)

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

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

符号连字符和 space 仍会出现在键盘中,但会被屏蔽。

keyboardType: TextInputType.number 会在焦点上打开一个数字键盘,我会在用户 enters/past 其他任何内容时清除文本字段。

keyboardType: TextInputType.number,
onChanged: (String newVal) {
    if(!isNumber(newVal)) {
        editingController.clear();
    }
}

// Function to validate the number
bool isNumber(String value) {
    if(value == null) {
        return true;
    }
    final n = num.tryParse(value);
    return n!= null;
}

这是 Android 上实际 Phone 键盘的代码:

关键部分:keyboardType: TextInputType.phone,

  TextFormField(
    style: TextStyle(
      fontSize: 24
    ),
    controller: _phoneNumberController,
    keyboardType: TextInputType.phone,
    decoration: InputDecoration(
      prefixText: "+1 ",
      labelText: 'Phone number'),
    validator: (String value) {
      if (value.isEmpty) {
        return 'Phone number (+x xxx-xxx-xxxx)';
      }
      return null;
    },
  ),

通过这个选项你可以严格限制另一个没有数字的字符。

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

要使用上述选项,您必须导入这个

import 'package:flutter/services.dart';

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

您可以将这两个属性与 TextFormField 一起使用

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

只允许输入数字,不能输入其他内容..

https://api.flutter.dev/flutter/services/TextInputFormatter-class.html

这是数字键盘的代码: keyboardType: TextInputType.phone 当您在文本字段中添加此代码时,它将打开数字键盘。

  final _mobileFocus = new FocusNode();
  final _mobile = TextEditingController();


     TextFormField(
          controller: _mobile,
          focusNode: _mobileFocus,
          maxLength: 10,
          keyboardType: TextInputType.phone,
          decoration: new InputDecoration(
            counterText: "",
            counterStyle: TextStyle(fontSize: 0),
            hintText: "Mobile",
            border: InputBorder.none,
            hintStyle: TextStyle(
              color: Colors.black,
                fontSize: 15.0.
            ),
          ),
          style: new TextStyle(
              color: Colors.black,
              fontSize: 15.0,
           ),
          );

对于数字输入或数字键盘,您可以使用键盘类型:TextInputType.number

TextFormField(
  decoration: InputDecoration(labelText:'Amount'),
    controller: TextEditingController(
  ),
  validator: (value) {
    if (value.isEmpty) {
      return 'Enter Amount';
    }
  },
  keyboardType: TextInputType.number
)

如果需要使用号:

keyboardType: TextInputType.numberWithOptions(decimal: true),
inputFormatters: [FilteringTextInputFormatter.allow(RegExp('[0-9.,]')),],
onChanged: (value) => doubleVar = double.parse(value),

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

double.parse() 从字符串转换为双精度。

别忘了你需要: import 'package:flutter/services.dart';

您可以使用 Form Builder Package 来显示任何类型的表单域。对于数字输入字段,

FormBuilderTextField(
     keyboardType: TextInputType.number,
     validators: [
          FormBuilderValidators.numeric(),
     ],
),

你可以安装包intl_phone_number_input

dependencies:
  intl_phone_number_input: ^0.5.2+2

并尝试此代码:

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

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    var darkTheme = ThemeData.dark().copyWith(primaryColor: Colors.blue);

    return MaterialApp(
      title: 'Demo',
      themeMode: ThemeMode.dark,
      darkTheme: darkTheme,
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: Scaffold(
        appBar: AppBar(title: Text('Demo')),
        body: MyHomePage(),
      ),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final GlobalKey<FormState> formKey = GlobalKey<FormState>();

  final TextEditingController controller = TextEditingController();
  String initialCountry = 'NG';
  PhoneNumber number = PhoneNumber(isoCode: 'NG');

  @override
  Widget build(BuildContext context) {
    return Form(
      key: formKey,
      child: Container(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            InternationalPhoneNumberInput(
              onInputChanged: (PhoneNumber number) {
                print(number.phoneNumber);
              },
              onInputValidated: (bool value) {
                print(value);
              },
              selectorConfig: SelectorConfig(
                selectorType: PhoneInputSelectorType.BOTTOM_SHEET,
                backgroundColor: Colors.black,
              ),
              ignoreBlank: false,
              autoValidateMode: AutovalidateMode.disabled,
              selectorTextStyle: TextStyle(color: Colors.black),
              initialValue: number,
              textFieldController: controller,
              inputBorder: OutlineInputBorder(),
            ),
            RaisedButton(
              onPressed: () {
                formKey.currentState.validate();
              },
              child: Text('Validate'),
            ),
            RaisedButton(
              onPressed: () {
                getPhoneNumber('+15417543010');
              },
              child: Text('Update'),
            ),
          ],
        ),
      ),
    );
  }

  void getPhoneNumber(String phoneNumber) async {
    PhoneNumber number =
        await PhoneNumber.getRegionInfoFromPhoneNumber(phoneNumber, 'US');

    setState(() {
      this.number = number;
    });
  }

  @override
  void dispose() {
    controller?.dispose();
    super.dispose();
  }
}

TextField 小部件需要设置 keyboardType: TextInputType.number, inputFormatters: <TextInputFormatter>[FilteringTextInputFormatter.digitsOnly] 仅接受数字作为输入。

     TextField(
            keyboardType: TextInputType.number,
            inputFormatters: <TextInputFormatter>[
              FilteringTextInputFormatter.digitsOnly
            ], // Only numbers can be entered
          ),

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

如已接受的答案所述,指定 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

您可以添加带有键盘类型的输入格式,像这样

TextField(
    inputFormatters: <TextInputFormatter>[
      FilteringTextInputFormatter.digitsOnly
    ],// Only numbers can be entered
    keyboardType: TextInputType.number,
   );

dart/flutter 中详细介绍了如何添加数字键盘、如何进行验证、如何添加样式以及其他内容。 希望能帮助大家更好的学习。

Padding(
            padding: const EdgeInsets.all(3.0),
            child: TextFormField(
              maxLength: 10,
              keyboardType: TextInputType.number,
              validator: (value) {
                if (value.isEmpty) {
                  return 'Enter Number Please';
                }
                
                return null;
              },
              decoration: InputDecoration(
                prefixIcon: Icon(Icons.smartphone),
                prefixText: '+92',
                labelText: 'Enter Phone Number',
                contentPadding: EdgeInsets.zero,
                enabledBorder: OutlineInputBorder(),
                focusedBorder: OutlineInputBorder(
                    borderSide: BorderSide(
                      width: 2, color: Theme
                        .of(context)
                        .primaryColor,
                    )
                ),
                focusColor: Theme
                    .of(context)
                    .primaryColor,
              ),
            ),
          ),

我需要一个控件为 min/max 的 IntegerFormField。最大的问题是焦点改变时不会调用 OnEditingComplete。这是我的解决方案:

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

class IntegerFormField extends StatefulWidget {
  final int value, min, max;
  final InputDecoration decoration;
  final ValueChanged<TextEditingController> onEditingComplete;
  IntegerFormField({@required this.value, InputDecoration decoration, onEditingComplete, int min, int max})
      : min = min ?? 0,
        max = max ?? maxIntValue,
        onEditingComplete = onEditingComplete ?? ((_) {}),
        decoration = decoration ?? InputDecoration()
  ;

  @override
  _State createState() => _State();
}

class _State extends State<IntegerFormField> {
  final TextEditingController controller = TextEditingController();

  @override
  void initState() {
    super.initState();
    controller.text = widget.value.toString();
  }

  @override
  void dispose() {
    super.dispose();
  }

  void onEditingComplete() {
    {
      try {
        if (int.parse(controller.text) < widget.min)
          controller.text = widget.min.toString();
        else if (int.parse(controller.text) > widget.max)
          controller.text = widget.max.toString();
        else
          FocusScope.of(context).unfocus();
      } catch (e) {
        controller.text = widget.value.toString();
      }
      widget.onEditingComplete(controller);
    }
  }

  @override
  Widget build(BuildContext context) {
    return Focus(
      child: TextFormField(
        controller: controller,
        inputFormatters: [FilteringTextInputFormatter.digitsOnly],
        keyboardType: TextInputType.number,
        decoration: widget.decoration,
      ),
      onFocusChange: (value) {
        if (value)
          controller.selection = TextSelection(baseOffset: 0, extentOffset: controller.value.text.length);
        else
          onEditingComplete();
      },
    );
  }
}

仅限数字类型

keyboardType: TextInputType.number

还有更多带数字键盘的选项

keyboardType: TextInputType.numberWithOptions(decimal: true,signed: false)

为避免粘贴不是数字值,请在

之后添加
keyboardType: TextInputType.number,

此代码:

inputFormatters: [FilteringTextInputFormatter.digitsOnly] 

来自 https://api.flutter.dev/flutter/services/FilteringTextInputFormatter-class.html

将您的键盘类型设置为 TextInputType.number,

例如:键盘类型:TextInputType.number,

         TextFormField(
            controller: yourcontroller,
            keyboardType: TextInputType.number,
            decoration: const InputDecoration(
              labelText: 'Mobile',
              suffixIcon: Padding(
                padding: EdgeInsets.only(),
                child:
                Icon(Icons.phone_outlined, color: Color(0xffff4876)),
              ),
            ),
            validator: (text) {
              if (text == null || text.isEmpty) {
                return 'Please enter your Mobile No.';
              }
              return null;
            },
          ),
TextField(
  controller: _controller,
  keyboardType: TextInputType.number,
  inputFormatters: <TextInputFormatter>[
  FilteringTextInputFormatter.allow(RegExp(r'[0.0-9.9]')),
 ])