flutter Form 表单组件的初步解析
文章目录
在一个正常的应用程序中, 表单是用户交互的很重要的一部分
flutter 中你可以自己"绑定"用户的输入数据和 state 中的字段
当然, 还有另一个选择, Flutter 内置了 Form
组件给我们使用, 这个组件是 flutter 框架提供出来帮助我们操作表单的一个组件, 应该是官方较为推荐的方案
不过 Form
的相关中文文章不太多, 基本都是介绍一下 TextFormField
的使用, 更多的 api 云里雾里的, 可能有些朋友不太好理解
我粗略的解析下源码和自定义, 帮助看过的朋友理解下 Form
体系
Form 体系的简单使用
自动校验
官方提供给了我们一些组件来结合 Form
使用, 最常见的就是 TextFormField
1import 'package:flutter/material.dart';
2
3class SimpleUseComponent extends StatefulWidget {
4 @override
5 _SimpleUseComponentState createState() => _SimpleUseComponentState();
6}
7
8class _SimpleUseComponentState extends State<SimpleUseComponent> {
9 @override
10 Widget build(BuildContext context) {
11 return Form(
12 onChanged: () {
13 print("form change");
14 },
15 child: Column(
16 children: <Widget>[
17 TextFormField(
18 initialValue: "你好",
19 validator: (value) {
20 if (value.isEmpty) return "不能为空";
21 return null;
22 },
23 autovalidate: true,
24 ),
25 ],
26 ),
27 );
28 }
29}
当我输入/删除时, 会出现日志: 'form change'
有一个
autovalidate
的属性, 这个属性可以在TextFormField
设置,也可以在Form
设置, 自动提交验证的意思, 默认是 false
.当我将所有字符都删除时, 会出现'不能为空'的提示. 这个是由
validator
实现的, 因为我设置了autovalidate
为 true
, 然后这个返回值如果是 null
, 则说明验证通过, 不通过则返回不通过的字符串.
点击后校验
当然,有些表单不要求自动校验, 可能是点击某个按钮后来校验, 这种情况下, 就需要使用 Form.of
来获取到表单状态
话不多说, 代码在下面:
1
2class SimpleUseClickComponent extends StatefulWidget {
3 @override
4 _SimpleUseClickComponentState createState() =>
5 _SimpleUseClickComponentState();
6}
7
8class _SimpleUseClickComponentState extends State<SimpleUseClickComponent> {
9 @override
10 Widget build(BuildContext context) {
11 return Form(
12 onChanged: () {
13 print("form change");
14 },
15 child: Column(
16 children: <Widget>[
17 TextFormField(
18 validator: (value) {
19 if (value.isEmpty) return "不能为空";
20 return null;
21 },
22 ),
23 Builder( // 这个 Builder 是
24 builder: (ctx) => RaisedButton(
25 child: Text('check'),
26 onPressed: () {
27 final formState = Form.of(ctx);
28 formState.validate(); // 验证
29 // formState.reset(); // 重置
30 // formState.save(); // 保存
31 },
32 ),
33 ),
34 ],
35 ),
36 );
37 }
38}
validate
会触发 FormState
的 validation
回调
reset
会触发 FormFieldState
的 reset
回调, 默认实现是将输入框设置为初始值
save
会触发 FormFieldState
的 save
回调, 可以在里面写一些逻辑(比如保存信息到数据库等等)
Form 体系源码
架构查看
Form
组件是 widgets 包内的的一个 Widget
, 不是 Material
和 Cupertino
包内的, 它没有用户界面, 更多的是逻辑层面的一个组件
Form
体系中有 5 个类, 3 个 typedef
组成
FormScope
是一个InheritedWidget
, 一般带of
方法的组件都会对应一个这个东西, 是获取 Form
中 FormState
的容器类
FormState
就是 Form
对应的 state
FormField
是Form
下的子组件的通用类, 每个实现/继承了这个类的子类就可以被Form
管理, 比如 TextFieldForm
就是这么一个组件
FormFieldState
是 FormField
对应的状态, 其中包含了一些状态信息
源码解析
通过回调等手段实现了内部的交互, 详细看截图
Form 解析
FormState 解析
FormField 解析
FormFieldState 解析
自定义 Form 子组件
有的时候表单中并不只有文本输入, 还会有 Checkbox
等组件, 我这里举两个例子来自定义一个 Form
子组件
自定义 CheckboxFormField
1import 'package:flutter/material.dart';
2
3class CheckboxFormField extends FormField<bool> {
4 CheckboxFormField({
5 bool initValue,
6 }) : super(
7 builder: CheckboxFormField.buildWidget,
8 initialValue: initValue,
9 );
10
11 static Widget buildWidget(FormFieldState<bool> field) {
12 return Checkbox(
13 onChanged: (bool value) {
14 field.didChange(value);
15 },
16 value: field.value,
17 );
18 }
19}
一个简单的自定义 CheckboxFormField
就完成了
置入 Form
中
1import 'package:flutter/material.dart';
2
3import 'custom_field.dart';
4
5class FormComponent extends StatefulWidget {
6 @override
7 _FormComponentState createState() => _FormComponentState();
8}
9
10class _FormComponentState extends State<FormComponent> {
11 @override
12 Widget build(BuildContext context) {
13 return Form(
14 onChanged: () {
15 print("on change");
16 },
17 child: ListView(
18 children: <Widget>[
19 CheckboxFormField(),
20 ],
21 ),
22 );
23 }
24}
当我点击时, 就会回调 on change
自定义 SliderFormField
1class SliderFormField extends FormField<double> {
2 SliderFormField()
3 : super(
4 builder: SliderFormField.buildWidget,
5 initialValue: 50,
6 );
7
8 static Widget buildWidget(FormFieldState<double> field) {
9 return Slider(
10 onChanged: (double value) {
11 field.didChange(value);
12 },
13 value: field.value,
14 min: 0,
15 max: 100,
16 divisions: 100,
17 );
18 }
19}
置入 Form 中
1import 'package:flutter/material.dart';
2
3import 'custom_field.dart';
4
5class FormComponent extends StatefulWidget {
6 @override
7 _FormComponentState createState() => _FormComponentState();
8}
9
10class _FormComponentState extends State<FormComponent> {
11 GlobalKey<FormState> formKey = GlobalKey();
12
13 @override
14 Widget build(BuildContext context) {
15 return Form(
16 key: formKey,
17 onChanged: () {
18 print("on change");
19 },
20 child: ListView(
21 children: <Widget>[
22 CheckboxFormField(),
23 SliderFormField(),
24 RaisedButton(
25 onPressed: () {
26 formKey.currentState.reset();
27 },
28 child: Text("reset"),
29 ),
30 ],
31 ),
32 );
33 }
34}
加入了一个Key
用于获取FormState
, 触发reset
方法
截图:
后记
本篇解析了一下 Form 的使用和源码, 帮助朋友们更好的理解使用
以上