[英]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- useTextFormField
.如果您在需要保存、重置或验证操作的地方制作
Form
使用TextFormField
。 Else For Simple user input captureTextField
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
回调。
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.
这是你应该首先掌握的。
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.这将使您可以访问文本状态。
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
}
},
),
],
),
);
}
}
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
TextFormField
与TextField
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
。
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()
上FormState
和FormState
将通过所有子迭代FormFields
登记,重设每一FormField
其initialValue
(默认为空)。
Validation is another common use case for putting several FormField
like TextFormField
inside Form
/ FormState
.验证是将多个
FormField
如TextFormField
放入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
并使用自定义代码分别验证要方便得多。
FormField
(base class of TextFormField
, etc.) make a call within their build()
method: Form.of(context)?._register(this);
FormField
( TextFormField
等的基类)在他们的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
如果有一个通话将只运行Form
与FormState
某处以上。
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
). (我们可以通过已注册为
dependOn
此FormState
子项触发Form
重建)。
TextFormField
is the deluxe package, air-conditioned, Bluetooth-connected 8-speaker stereo version of TextField
. TextFormField
是TextField
的豪华包、空调、蓝牙连接的 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
: AFormField
that contains aTextField
.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 组件Checkbox
的FormField
:
// 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.