我是Flutter(和Dart)的新手,在尝试构建用于编辑对象的表单时,我在网上搜索了示例和教程,并且看到了这两种用法。
2和有什么区别?我应该使用哪一个?
谢谢。
答案 0 :(得分:9)
如果您不知道需要什么,请使用TextField
。这是用于从用户获取文本输入的最基本的Flutter小部件。这是您应该首先掌握的。
使用TextField
是允许用户输入的简便方法。
TextField(
decoration: InputDecoration(
hintText: 'Name'
),
);
要获取用户输入的文字,每次发生这样的更改时,您都可以得到通知:
TextField(
decoration: InputDecoration(
hintText: 'Name'
),
onChanged: (text) {
// do something with text
},
),
或者您可以使用here中所述的TextEditingController
。这将使您可以访问文本状态。
如果发现保存之前需要验证用户文本输入,则可以考虑使用TextFormField
。想象这样的事情:
您可能需要对用户名和密码进行很多验证检查。
当然,您仍然可以只使用几个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">❮</a>
<a class="imgbtn nxtbtn" id="nxtbtn">❯</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()
上调用 FormState
,FormState
将遍历所有注册的子 FormFields
,将每个 FormField
重置为它的 initialValue
(默认为 null)。
验证是将多个 FormField
(例如 TextFormField
)放入 Form
/FormState
的另一个常见用例。这允许使用 validate()
上的单个 Form
调用来验证多个字段。
怎么样? FormState
有一个 validate()
方法,它遍历每个注册的 FormField
并调用该 FormField's
validate()
方法。在 validate()
上调用一次 Form
比手动跟踪所有 TextField
并使用自定义代码单独验证每个 FormField
方便得多。
TextFormField
(build()
的基类等)在其 Form.of(context)?._register(this);
方法中进行调用:
Form
在英语中,这意味着:
搜索我的上下文层次结构,直到我们找到一个 ?
小部件(如果有)并使用该表单注册自己。
Form
是在没有 _register
小部件父级的情况下。 Form
调用将仅在 if 上面是一个 FormState
和 Form.of(context)?._register(this)
时运行。
Form
是如何工作的?FormState
和 InheritedWidget
偷偷使用 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
的重建。
TextField
是 let 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 扬声器立体声版本。它包含许多您在接受用户输入的信息时会用到的常用功能。