TextFormField和TextField有什么区别?

时间:2019-02-13 02:28:28

标签: flutter

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

2和有什么区别?我应该使用哪一个?

谢谢。

4 个答案:

答案 0 :(得分:9)

简短回答

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

TextField

使用TextField是允许用户输入的简便方法。

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

enter image description here

要获取用户输入的文字,每次发生这样的更改时,您都可以得到通知:

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

或者您可以使用here中所述的TextEditingController。这将使您可以访问文本状态。

TextFormField

如果发现保存之前需要验证用户文本输入,则可以考虑使用TextFormField。想象这样的事情:

enter image description here

您可能需要对用户名和密码进行很多验证检查。

当然,您仍然可以只使用几个TextField,但是TextFormField具有额外的内置功能,可以使您的生活更轻松。通常,只有在TextFormField小部件内使用Form时才使用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 } }, ), ], ), ); } } (尽管不是严格要求)。

以下是documentation中的一个精简示例:

import openpyxl
wb1 = openpyxl.load_workbook("unmerge.xlsx")
wb1sh2 = wb1["sh2"]
wb1sh2.unmerge_cells("A7:A8")

另请参见

答案 1 :(得分:3)

  

如果在需要保存,重置或验证的地方进行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;
  },
)

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

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

答案 2 :(得分:2)

<html> <body> <div id="imgtabs"> <div class="tab" id="ban1"> <h3>First</h3> </div> <div class="tab" id="ban2"> <h3>Second</h3> </div> <div class="tab" id="ban3"> <h3>Third</h3> </div> <a class="imgbtn prvbtn" id="prvbtn">&#10094;</a> <a class="imgbtn nxtbtn" id="nxtbtn">&#10095;</a> </div> </body> </html>是一个简单的文本字段。 (您不在乎用户输入) TextField是用于表单的文本字段(您在乎用户输入)。

如果您不需要验证TextFormField。 如果您需要验证用户输入,请将TextFormField与TextField一起使用。

答案 3 :(得分:2)

TextFormField 对比 TextField

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

通常,除非您喜欢编写样板代码,否则您希望使用 TextFormField

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

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

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

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

例如要清除整个表单,我们可以在 reset() 上调用 FormStateFormState 将遍历所有注册的子 FormFields,将每个 FormField 重置为它的 initialValue(默认为 null)。

验证是将多个 FormField(例如 TextFormField)放入 Form/FormState 的另一个常见用例。这允许使用 validate() 上的单个 Form 调用来验证多个字段。

怎么样? FormState 有一个 validate() 方法,它遍历每个注册的 FormField 并调用该 FormField's validate() 方法。在 validate() 上调用一次 Form 比手动跟踪所有 TextField 并使用自定义代码单独验证每个 FormField 方便得多。

详情

TextFormField 如何向表单注册自己?

TextFormFieldbuild() 的基类等)在其 Form.of(context)?._register(this); 方法中进行调用: Form

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

Form 是在没有 _register 小部件父级的情况下。 Form 调用将仅在 if 上面一个 FormStateForm.of(context)?._register(this) 时运行。

Form 是如何工作的?

FormStateInheritedWidget 偷偷使用 FormState。 在 return WillPopScope( onWillPop: widget.onWillPop, child: _FormScope( // ← sneaky formState: this, generation: _generation, child: widget.child, ), ); .build() 中,您将看到以下代码:

_FormScope

看着 class _FormScope extends InheritedWidget ,我们看到:

InheritedWidget

当父小部件是 Form 时,任何孩子都可以使用特殊的“为我找到这种类型的父” 方法找到该父小部件。

以下是“find me”方法如何在 static FormState of(BuildContext context) { final _FormScope scope = context.dependOnInheritedWidgetOfExactType<_FormScope>(); return scope?._formState; } 中使用/公开作为我们可以从任何地方调用的静态方法:

dependOnInheritedWidgetOfExactType

该方法 findInheritedWidgetOfExactType 的命名有点棘手。 Form 会更易读,但它不仅仅是查找。 (我们可以通过注册为 dependOn this FormState 的子代触发 TextFormField 的重建。

总结

TextFieldlet loginManager = LoginManager() // Ensure the configuration object is valid guard let configuration = LoginConfiguration(tracking: .limited, nonce: "123") else { return } loginManager.logIn(configuration: configuration) { result in switch result { case .cancelled, .failed: // Handle error break case .success: // getting user ID let userID = Profile.current?.userID // getting pre-populated email let email = Profile.current?.email // getting id token string let tokenString = AuthenticationToken.current?.tokenString } } 的豪华套装、空调、蓝牙连接 8 扬声器立体声版本。它包含许多您在接受用户输入的信息时会用到的常用功能。