当前位置:网站首页>Flutter 从零开始 008 表单
Flutter 从零开始 008 表单
2022-06-30 10:46:00 【华为云】
表单Form
在实际业务开发中,在正式像服务器提交数据之前,都会对各个输入框数据进行合法性校验,但是对每一个TextField 都进行校验是一件很麻烦的事。如果用户想清除一组TextField 的数据,又非常的麻烦。flutter还给我们提供了一个From 组件,它可以对输入框进行分组,然后进行统一操作,如内容校验,输入框重置,输入内容保存等。
Form继承自StatefulWidget对象,它对应的状态类为FormState。我们先看看Form类的定义:
Form({ required Widget child, bool autovalidate = false, WillPopCallback onWillPop, VoidCallback onChanged,})autovalidate : 是否自动校验输入内容,当为true 时,每个子FormFeild 内容发生变化时,都会自动校验合法性,并直接显示错误信息。否则,需要通过调用FormState.validate() 来手动校验。
onWillPop: 决定Form 所在的路由是否可以直接返回(如点击返回按钮),该回调返回一个Future对象,如果 Future 的最终结果是false,则当前路由不会返回;如果为true,则会返回到上一个路由。此属性通常用于拦截返回按钮。
onChanged:Form的任意一个子FormField内容发生变化时会触发此回调。
Form的子孙元素必须是FormField类型,FormField是一个抽象类,定义几个属性,FormState内部通过它们来完成操作,FormField部分定义如下:
const FormField({ ... FormFieldSetter<T> onSaved, //保存回调 FormFieldValidator<T> validator, //验证回调 T initialValue, //初始值 bool autovalidate = false, //是否自动校验。})为了方便使用,Flutter 提供了一个TextFormField组件,它继承自FormField类,也是TextField的一个包装类,所以除了FormField定义的属性之外,它还包括TextField的属性。
FormState为Form的State类,可以通过Form.of()或GlobalKey获得。我们可以通过它来对Form的子孙FormField进行统一操作。我们看看其常用的三个方法:
FormState.validate():调用此方法后,会调用Form子孙FormField的validate回调,如果有一个校验失败,则返回false,所有校验失败项都会返回用户返回的错误提示。
FormState.save():调用此方法后,会调用Form子孙FormField的save回调,用于保存表单内容
FormState.reset():调用此方法后,会将子孙FormField的内容清空。
示例
我们修改一下上面用户登录的示例,在提交之前校验:
用户名不能为空,如果为空则提示“用户名不能为空”。
密码不能小于 6 位,如果小于 6 为则提示“密码不能少于 6 位”。
class _MyHomePageState extends State<MyHomePage> { TextEditingController userController = TextEditingController(); TextEditingController passController = TextEditingController(); GlobalKey _globalKey = GlobalKey<FormState>(); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text(widget.title), ), body: Form( key: _globalKey, //设置globalKey,用于后面获取FormState autovalidateMode: AutovalidateMode.onUserInteraction, child: Column( children: [ TextFormField( autofocus: true, controller: userController, decoration: InputDecoration( labelText: "用户名", hintText: "用户名或邮箱", icon: Icon(Icons.person), ), validator: (v) { return v!.trim().isNotEmpty ? null : '用户名不能为空'; }, ), SizedBox( height: 20, ), TextFormField( controller: passController, decoration: InputDecoration( labelText: "密码", hintText: "输入密码", icon: Icon(Icons.lock), ), obscureText: true, validator: (v) { return v!.trim().length > 5 ? null : '密码不能少于6位'; }, ), Padding( padding: EdgeInsets.only(top: 20), child: Expanded( child: ElevatedButton( child: Padding( padding: EdgeInsets.all(16), child: Text("登录"), ), onPressed: () { // 通过_formKey.currentState 获取FormState后, // 调用validate()方法校验用户名密码是否合法,校验 // 通过后再提交数据。 if((_globalKey.currentState as FormState).validate()){ print("验证通过,开始提交"); } }, ), ), ), ], ), ), ); }}运行效果如下

注意,登录按钮的onPressed方法中不能通过Form.of(context)来获取,原因是,此处的context为FormTestRoute的context,而Form.of(context)是根据所指定context向根去查找,而FormState是在FormTestRoute的子树中,所以不行。正确的做法是通过Builder来构建登录按钮,Builder会将widget节点的context作为回调参数:
Expanded( // 通过Builder来获取ElevatedButton所在widget树的真正context(Element) child:Builder(builder: (context){ return ElevatedButton( ... onPressed: () { //由于本widget也是Form的子代widget,所以可以通过下面方式获取FormState if(Form.of(context).validate()){ //验证通过提交数据 } }, ); }))下一节我们将介绍指示器
边栏推荐
- 深潜Kotlin协程(十八):冷热数据流
- ARouter 最新问题合集
- LVGL 8.2 Simple Image button
- 100 important knowledge points that SQL must master: using subquery
- 在IPhone12的推理延迟仅为1.6 ms!Snap等详析Transformer结构延迟,并用NAS搜出移动设备的高效网络结构...
- Qt之实现QQ天气预报窗体翻转效果
- 林克庆到番禺区调研“发展要安全”工作 以“时时放心不下”责任感抓好安全发展各项工作
- Ant financial's written test question: what can be quantified in the requirements document? [Hangzhou multi tester] [Hangzhou multi tester \wang Sir]
- Deep dive kotlin synergy (18): hot and cold data flow
- 数据库什么时候需要使用索引【杭州多测师】【杭州多测师_王sir】
猜你喜欢

Wireguard simple configuration

深潜Kotlin协程(十六):Channel

Review of mathematical knowledge: curve integral of the second type

Mysql database foundation: views and variables

The reasoning delay on iphone12 is only 1.6 MS! Snap et al. Analyzed the transformer structure latency in detail, and used NAS to find out the efficient network structure of mobile devices

The life, working principle and application of electrochemical oxygen sensor

微信表情符号被写入判决书,你发的每个 emoji 都可能成为呈堂证供

LVGL 8.2 Image

中移OneOS开发板学习入门
![200000 bonus pool! [Alibaba security × ICDM 2022] the risk commodity inspection competition on the large-scale e-commerce map is in hot registration](/img/0e/19c4c97a582d7b2ad08ce806d7af03.jpg)
200000 bonus pool! [Alibaba security × ICDM 2022] the risk commodity inspection competition on the large-scale e-commerce map is in hot registration
随机推荐
数学知识复习:第二型曲线积分
DQN笔记
SQL必需掌握的100个重要知识点:分组数据
datax - 艰难debug路
100 important knowledge points that SQL must master: join table
Go语言学习之Switch语句的使用
The number of users of the home-made self-developed system exceeded 400million, breaking the monopoly of American enterprises, and Google repented
List introduction
小程序中读取腾讯文档的表格数据
Algorithme leetcode 86. Liste des liens séparés
[understanding of opportunity -34]: fate is within the light cone
LVGL 8.2 Simple Colorwheel
SQL必需掌握的100个重要知识点:使用子查询
语音信号处理-基础(五):傅立叶变换
promise async和await的方法与使用
记一次ViewPager + RecyclerView的内存泄漏
LVGL 8.2 Simple Drop down list
Kotlin 协程调度切换线程是时候解开谜团了
The intelligent DNA molecular nano robot model is coming
训练一个图像分类器demo in PyTorch【学习笔记】