TextFormField和TextField有什么区别?

ccc*_*ccc 19 flutter

我是Flutter(和Dart)的新手,在尝试构建用于编辑对象的表单时,我在网上搜索了示例和教程,而我看到了这两种用法。

2和有什么不一样?我应该使用哪一个?

谢谢。

Sur*_*gch 22

简答

如果您不知道自己需要什么,请使用TextField. 这是最基本的 Flutter 小部件,用于从用户那里获取文本输入。这是你应该首先掌握的。

文本域

使用 aTextField是一种允许用户输入的简单方法。

TextField(
  decoration: InputDecoration(
    hintText: 'Name'
  ),
);
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

要获取用户输入的文本,您可以在每次发生如下更改时收到通知:

TextField(
  decoration: InputDecoration(
      hintText: 'Name'
  ),
  onChanged: (text) {
    // do something with text
  },
),
Run Code Online (Sandbox Code Playgroud)

或者你也可以使用TextEditingController,如所描述这里。这将使您可以访问文本状态。

文本表单域

如果您发现自己需要在保存之前验证用户文本输入,您可以考虑使用TextFormField. 想象一下这样的事情:

在此处输入图片说明

您可能希望对用户名和密码进行许多验证检查。

当然,您仍然可以只使用几个 TextField,但TextFormField具有额外的内置功能,可以让您的生活更轻松。通常,只有TextFormFieldForm小部件内部使用时才会使用 a (尽管这不是严格要求)。

这是文档中的一个精简示例:

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
              }
            },
          ),
        ],
      ),
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

也可以看看


anm*_*ail 17

如果Form在需要保存,重置或验证操作的地方进行使用,请使用TextFormField。其他简单用户输入捕获 TextField就足够了。

TextFormField,与Form小部件集成。

这是一个方便的小部件,将TextField小部件包装在FormField中。

一个Form不需要祖先。该表单使一次保存,重置或验证多个字段变得更加容易。

要在没有表单的情况下使用,请将GlobalKey传递给构造函数,然后使用GlobalKey.currentState保存或重置表单字段。

样品:

TextFormField(
  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;
  },
)
Run Code Online (Sandbox Code Playgroud)

TextField,这是没有Form集成的基础文本字段。

onChanged每当用户更改字段中的文本时,文本字段就会调用回调。如果用户指示他们已完成在字段中的键入(例如,通过按软键盘上的按钮),则文本字段将调用onSubmitted回调。

  • 这个答案是此处文档中显示的示例:https://api.flutter.dev/flutter/material/TextFormField-class.html (3认同)

Rub*_*elo 15

TextField是一个简单的文本字段。(您不关心用户输入) TextFormField是要在表单中使用的文本字段(您关心用户输入)。

如果您不需要验证TextField. 如果您需要验证用户输入,请将 TextFormField 与validator.

  • “(你不关心用户输入)”我们当然关心 :D 它只是不是表单的一部分。 (14认同)

Son*_*yen 9

我认为这可能是关于两者之间差异的最简洁明了的解释。

来自材料库

TextField:材料设计文本字段。

TextFormField:FormField包含TextField.

同样,您可以包装FormField任何库比蒂诺输入组件,例如CupertinoTextField

下面是一个关于自定义的示例CheckboxFormField,它是FormField围绕材料设计组件的Checkbox

// 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),
          ),
      ],
    );
  },
),
Run Code Online (Sandbox Code Playgroud)

经验法则:如果您的盒子只有一个输入字段,只需使用原材料输入即可TextFieldFormField尽管在这种情况下有点矫枉过正)。如果您的框有许多输入字段,您需要将每个输入字段包装在 中FormField,然后将它们全部集成到Form小部件中,以获得一次性验证和保存所有表单字段的好处。

额外提示:如果您有一个TextField包裹在 a 中的组件FormField,不允许用户输入任何文本,例如 aCupertinoPickerFormField或 a SimpleDialogFormField,它为用户提供了多个选项之间的选择(这基本上是一个SimpleDialog包裹在 a 中的材质小部件FormField),只需使用不使用的 hintText参数来操作文本。使用 使提示文本的颜色与正常输入文本的颜色相同。InputDecorationTextEditingControllerhintStyle: const TextStyle(color: Color(0xdd000000))

来自 Flutter Europe 的这段视频将帮助您立即掌握 Flutter 中的表单。


Bak*_*ker 5

TextFormField 对比 TextField

TextFormField返回 a TextField,但包含了TextField额外的功能,您可以通过 a 使用Form,也可以不使用(例如重置、验证、保存等)。

通常,TextFormField除非您喜欢编写样板代码,否则您想使用它。

如何TextFormField工作?它能做什么?

TextFormField扩展FormField类,(a StatefulWidget)。 FormField对象在实例化时会做一件特别的事情:它们在小部件树中查找 aForm并使用 that 注册自己Form

注册后,这些FormField小部件可以由该父级更改Form

Form也是一个StatefulWidget。它有一个FormState对象。 FormState可以获取和设置任何/所有FormFields注册到它的数据。

例如,要清除整个表格我们可以调用reset()FormState,并FormState会通过所有的孩子重复FormFields登记,重设每一FormFieldinitialValue(默认为空)。

验证是将多个FormFieldlikeTextFormField放入 Form/ 的另一个常见用例FormState。这允许通过单个validate()调用来验证多个字段Form

如何? FormState有一个validate()方法可以遍历每个注册FormField并调用该FormField's validate()方法。与手动跟踪所有内容并使用自定义代码单独验证每个validate()内容Form相比,一次调用要方便得多TextField

细节

TextFormField 如何向 Form 注册自己?

FormField(等的基类TextFormField)在他们的build()方法中进行调用: Form.of(context)?._register(this);

在英语中,这意味着: 搜索我的上下文层次结构,直到我们找到一个Form小部件(如果有)并使用该表单注册我自己。

?是在没有Form小部件父级的情况下。的_register通话将只运行,如果一个FormFormState上面的某个地方。

如何Form.of(context)?._register(this)工作?

Form&FormState偷偷地使用InheritedWidget。在FormState.build() 你会看到这个代码:

return WillPopScope(
      onWillPop: widget.onWillPop,
      child: _FormScope( // ? sneaky
        formState: this,
        generation: _generation,
        child: widget.child,
      ),
    );
Run Code Online (Sandbox Code Playgroud)

_FormScope我们看到:

class _FormScope extends InheritedWidget
Run Code Online (Sandbox Code Playgroud)

当父小部件是 时InheritedWidget,任何孩子都可以使用特殊的“为我找到此确切类型的父级”方法找到该父级

以下是“find me”方法如何在内部使用/公开Form为我们可以从任何地方调用的静态方法:

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

该方法的命名dependOnInheritedWidgetOfExactType有点棘手。它会更易读findInheritedWidgetOfExactType,但它不仅仅是查找。(我们可以触发Form注册为dependOnthis的through children 的重建FormState)。

概括

TextFormField是豪华套餐、空调、蓝牙连接的 8 扬声器立体声版本TextField。它包括许多您在接受用户输入的信息时会用到的常用功能。