简体   繁体   English

TextFormField 和 TextField 有什么区别?

[英]What is the difference between TextFormField and TextField?

I am new to Flutter (and Dart) and when trying to build a form to edit an object I searched online for examples and tutorials, and I saw both of these used.我是 Flutter(和 Dart)的新手,当我尝试构建一个表单来编辑对象时,我在网上搜索了示例和教程,我看到这两个都被使用了。

What is the difference between the two?两者有什么区别? Which one should I use?我应该使用哪一种?

If you making a Form where you require save, reset, or validate operations- use TextFormField .如果您在需要保存、重置或验证操作的地方制作Form使用TextFormField Else For Simple user input capture TextField is sufficient. Else 对于简单的用户输入捕获TextField就足够了。

TextFormField , which integrates with the Form widget. TextFormField ,它与Form小部件集成。

This is a convenience widget that wraps a TextField widget in a FormField.这是一个方便的小部件,它将 TextField 小部件包装在 FormField 中。

A Form ancestor is not required.不需要Form祖先。 The Form simply makes it easier to save, reset, or validate multiple fields at once .表单只是使一次保存、重置或验证多个字段变得更容易。

To use without a Form, pass a GlobalKey to the constructor and use GlobalKey.currentState to save or reset the form field.要在没有 Form 的情况下使用,请将 GlobalKey 传递给构造函数并使用 GlobalKey.currentState 来保存或重置表单字段。

sample:样本:

TextFormField(
  autovalidateMode: AutovalidateMode.always
  decoration: const InputDecoration(
    icon: Icon(Icons.person),
    hintText: 'What do people call you?',
    labelText: 'Name *',
  ),
  onSaved: (String value) {
    // This optional block of code can be used to run
    // code when the user saves the form.
  },
  validator: (String value) {
    return value.contains('@') ? 'Do not use the @ char.' : null;
  },
)

TextField , which is the underlying text field without the Form integration. TextField ,它是没有Form集成的底层文本字段。

The text field calls the onChanged callback whenever the user changes the text in the field.每当用户更改字段中的文本时,文本字段都会调用onChanged回调。 If the user indicates that they are done typing in the field (eg, by pressing a button on the soft keyboard), the text field calls the onSubmitted callback.如果用户指示他们已完成在字段中的输入(例如,通过按下软键盘上的按钮),则文本字段将调用onSubmitted回调。

Short answer简答

If you don't know what you need, then use a TextField .如果您不知道自己需要什么,请使用TextField This is the most basic Flutter widget for getting text input from a user.这是最基本的 Flutter 小部件,用于从用户那里获取文本输入。 It's the one you should master first.这是你应该首先掌握的。

TextField文本域

Using a TextField is an easy way to allow user input.使用TextField是一种允许用户输入的简单方法。

TextField(
  decoration: InputDecoration(
    hintText: 'Name'
  ),
);

在此处输入图片说明

To get the text that the user entered, you can either get notified every time there is a change like this:要获取用户输入的文本,您可以在每次发生如下更改时收到通知:

TextField(
  decoration: InputDecoration(
      hintText: 'Name'
  ),
  onChanged: (text) {
    // do something with text
  },
),

Or you can use a TextEditingController , as described here .或者你可以使用一个TextEditingController ,描述在这里 This will give you access to the text state.这将使您可以访问文本状态。

TextFormField文本表单域

If you find yourself needing to validate user text input before you save it, you might consider using a TextFormField .如果您发现自己需要在保存之前验证用户文本输入,您可以考虑使用TextFormField Imagine something like this:想象一下这样的事情:

在此处输入图片说明

There are lots of validation checks that you might want to do on a username and password.您可能希望对用户名和密码进行许多验证检查。

Of course, you could still just use a couple TextFields, but TextFormField has extra builtin functionality that will make your life easier.当然,您仍然可以只使用几个 TextField,但TextFormField具有额外的内置功能,可以让您的生活更轻松。 Generally, you will only use a TextFormField when you are using it inside of a Form widget (though that isn't a strict requirement).通常,当您在Form小部件中使用TextFormField时,您只会使用它(尽管这不是严格的要求)。

Here is a stripped down example from the documentation :这是文档中的一个精简示例:

class MyCustomForm extends StatefulWidget {
  @override
  MyCustomFormState createState() {
    return MyCustomFormState();
  }
}

class MyCustomFormState extends State<MyCustomForm> {
  final _formKey = GlobalKey<FormState>();

  @override
  Widget build(BuildContext context) {
    return Form(
      key: _formKey,
      child: Column(
        children: <Widget>[
          TextFormField(
            validator: (value) {
              // validation logic
            },
          ),
          RaisedButton(
            child: Text('Submit'),
            onPressed: () {
              if (_formKey.currentState.validate()) {
                // text in form is valid
              }
            },
          ),
        ],
      ),
    );
  }
}

See also也可以看看

TextField is a simple text field. TextField是一个简单的文本字段。 (you don't care about user input) TextFormField is a text field to be used in a form (you care about user input). (您不关心用户输入) TextFormField是要在表单中使用的文本字段(您关心用户输入)。

If you don't need to validate TextField .如果您不需要验证TextField If you need to validate user input, use TextFormField with validator .如果您需要验证用户输入,请将 TextFormField 与validator使用。

TextFormField vs. TextField TextFormFieldTextField

TextFormField returns a TextField , but wraps the TextField with extra functionality you can use through a Form and also without (such as reset, validation, save, etc.). TextFormField返回一个TextField ,但用额外的功能包装TextField ,您可以通过Form使用,也可以不使用(例如重置、验证、保存等)。

Generally, you want to use TextFormField unless writing boiler-plate code is your thing.通常,除非您喜欢编写样板代码,否则您希望使用TextFormField

How does TextFormField work? TextFormField如何工作? What can it do?它能做什么?

TextFormField extends FormField class, (a StatefulWidget ). TextFormField扩展了FormField类(一个StatefulWidget )。 FormField objects do a special thing when they are instantiated: they look up the widget tree for a Form and register themselves with that Form . FormField对象在实例化时会做一件特别的事情:它们在小部件树中查找Form并使用该Form注册自己。

After registration, these FormField widgets can be changed by that parent Form .注册后,这些FormField小部件可以由该父Form更改。

Form is also a StatefulWidget . Form也是一个StatefulWidget It has a FormState object.它有一个FormState对象。 FormState can get & set data on any/all FormFields registered to it. FormState可以获取和设置注册到它的任何/所有FormFields上的数据。

For example to clear the entire form we can call reset() on FormState and FormState will iterate through all child FormFields registered, resetting each FormField to its initialValue (null by default).例如,要清除整个表格,我们可以调用reset()FormStateFormState将通过所有子迭代FormFields登记,重设每一FormFieldinitialValue (默认为空)。

Validation is another common use case for putting several FormField like TextFormField inside Form / FormState .验证是将多个FormFieldTextFormField放入Form / FormState另一个常见用例。 This allows multiple fields to be validated with a single validate() call on the Form .这允许使用Form上的单个validate()调用来验证多个字段。

How?如何? FormState has a validate() method that iterates through each registered FormField and calls that FormField's validate() method. FormState有一个validate()方法,它遍历每个注册的FormField并调用该FormField's validate()方法。 Much more convenient calling validate() once on Form than you manually keeping track of all TextField and validating each one separately with custom code.Form上调用一次validate()比手动跟踪所有TextField并使用自定义代码分别验证要方便得多。

Details细节

How does a TextFormField register itself with a Form? TextFormField 如何向 Form 注册自己?

FormField (base class of TextFormField , etc.) make a call within their build() method: Form.of(context)?._register(this); FormFieldTextFormField等的基类)在他们的build()方法中调用: Form.of(context)?._register(this);

In English this means: Search up my context hierarchy until we find a Form widget (if any) and register myself with that form.在英语中,这意味着:搜索我的上下文层次结构,直到我们找到一个Form小部件(如果有)并在该表单中注册我自己。

The ? ? is in case there is no Form widget parent.如果没有Form小部件父级。 The _register call will only be run if there is a Form & FormState somewhere above._register如果一个通话将只运行FormFormState某处以上。

How does Form.of(context)?._register(this) work? Form.of(context)?._register(this)工作?

Form & FormState sneakily use InheritedWidget . Form & FormState偷偷地使用InheritedWidget In FormState .build() you'll see this code:FormState () 中,您将看到以下代码:

return WillPopScope(
      onWillPop: widget.onWillPop,
      child: _FormScope( // ← sneaky
        formState: this,
        generation: _generation,
        child: widget.child,
      ),
    );

Looking at _FormScope we see:查看_FormScope我们看到:

class _FormScope extends InheritedWidget

When a parent widget is an InheritedWidget , any child can find that parent using a special "find me a parent of this exact Type" method.当父小部件是InheritedWidget ,任何孩子都可以使用特殊的“为我找到此确切类型的父级”方法找到该父级

Here's how that "find me" method is used/exposed inside Form as a static method we can call from anywhere:以下是“找到我”方法如何在Form使用/公开作为我们可以从任何地方调用的静态方法:

static FormState of(BuildContext context) {
    final _FormScope scope = context.dependOnInheritedWidgetOfExactType<_FormScope>();
    return scope?._formState;
  }

The naming of that method dependOnInheritedWidgetOfExactType is a bit tricky.该方法的命名dependOnInheritedWidgetOfExactType有点棘手。 It'd be more readable as findInheritedWidgetOfExactType , but it does more than just find.作为findInheritedWidgetOfExactType会更易读,但它不仅仅是查找。 (We can trigger rebuilds of Form through children that have registered as dependOn this FormState ). (我们可以通过已注册为dependOnFormState子项触发Form重建)。

Summary概括

TextFormField is the deluxe package, air-conditioned, Bluetooth-connected 8-speaker stereo version of TextField . TextFormFieldTextField的豪华包、空调、蓝牙连接的 8 扬声器立体声版本。 It includes a lot of common functionality you would use when accepting user-entered information.它包括许多您在接受用户输入的信息时会用到的常用功能。

( May 2021 ) I think this might be the most concise and simple explanation about the differences between the two. 2021 年 5 月)我认为这可能是对两者差异的最简洁明了的解释。

From the material library :材料库

TextField : A material design text field. TextField :材料设计文本字段。

TextFormField : A FormField that contains a TextField . TextFormField :包含TextField FormField

Similarly, you can wrap FormField around any cupertino input component such as CupertinoTextField同样,您可以将FormField包裹在任何 Cupertino 输入组件中,例如CupertinoTextField

Below is an example about a custom CheckboxFormField , which is a FormField that wraps around the material design component Checkbox :下面是一个关于自定义CheckboxFormField的示例,它是一个环绕 Material Design 组件CheckboxFormField

// A custom CheckboxFormField, which is similar to the built-in TextFormField
bool agreedToTerms = false;
FormField(
  initialValue: false,
  validator: (value) {
    if (value == false) {
      return 'You must agree to the terms of service.';
    }
    return null;
  },
  builder: (FormFieldState formFieldState) {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Row(
          children: [
            Checkbox(
              value: agreedToTerms,
              onChanged: (value) {
                // When the value of the checkbox changes,
                // update the FormFieldState so the form is
                // re-validated.
                formFieldState.didChange(value);
                setState(() {
                  agreedToTerms = value;
                });
              },
            ),
            Text(
              'I agree to the terms of service.',
              style: Theme.of(context).textTheme.subtitle1,
            ),
          ],
        ),
        if (!formFieldState.isValid)
          Text(
            formFieldState.errorText ?? "",
            style: Theme.of(context)
                .textTheme
                .caption
                .copyWith(color: Theme.of(context).errorColor),
          ),
      ],
    );
  },
),

Rule of thumb : If your box only have a single input field, just use the raw material input like TextField ( FormField is a bit overkill in this case though).经验法则:如果您的盒子只有一个输入字段,只需使用像TextField这样的原材料输入(尽管在这种情况下FormField有点矫枉过正)。 If your box has many input fields, you need to wrap each one of them in a FormField , and then integrate all of them to the Form widget to reap the benefits of validating or saving multiple fields at once如果您的框有许多输入字段,您需要将它们中的每一个都包装在一个FormField ,然后将它们全部集成到Form小部件中,以获得一次验证或保存多个字段的好处

This video from Flutter Europe will help you master forms in Flutter quickly这个来自 Flutter Europe 的视频将帮助你快速掌握 Flutter 中的表单

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Flutter textField 小部件中的 onSubmitted 和 onEditingComplete 有什么区别? - What is the difference between onSubmitted and onEditingComplete in Flutter textField widget? Flutter TextField 与 TextFormField - Flutter TextField vs TextFormField Flutter:将字符串解析为 TextField/TextFormField - Flutter : Parsing String to TextField/ TextFormField Flutter:带有 TextField/TextFormField 的底部工作表 - Flutter: Bottom sheet with TextField/TextFormField Flutter:onEdittingComplete 和 onSubmitted 之间的 TextField 差异 - Flutter: TextField difference between onEdittingComplete and onSubmitted Flutter:如何以编程方式添加 TextField 或 TextFormField - Flutter: How to add a TextField or TextFormField programmatically 我想验证 flutter 中的“文本”不是(TextFormField 或 Textfield) - I want to validate "Text" in flutter not (TextFormField or Textfield) Flutter:如何在 TextField/TextFormField 中正确插入文本 - Flutter: How to insert text properly in a TextField/TextFormField 复制和粘贴在 Flutter 的 TextFormField 和 TextField 中不起作用 - Copy and Paste not working in TextFormField & TextField in Flutter Flutter 应用程序在选择 TextField 或 TextFormField 时冻结 - Flutter app freezes when a TextField or TextFormField is selected
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM