6.1 TextFormWidget 组件封装
 
预备知识
Form继承自StatefulWidget对象,它对应的状态类为FormState。
Form类的定义:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 
 | class Form extends StatefulWidget {
 final Widget child;
 
 
 
 
 final WillPopCallback? onWillPop;
 
 
 final VoidCallback? onChanged;
 
 
 
 final AutovalidateMode autovalidateMode;
 
 | 
Form的子孙元素必须是FormField类型,FormField是一个抽象类,定义几个属性,FormState内部通过它们来完成操作,FormField部分定义如下:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 
 | class FormField<T> extends StatefulWidget {
 
 
 final FormFieldSetter<T>? onSaved;
 
 
 final FormFieldValidator<T>? validator;
 
 
 final T? initialValue;
 
 
 final bool enabled;
 
 
 final AutovalidateMode autovalidateMode;
 
 | 
TextFormField
为了方便使用,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的内容清空。
 
实现步骤:
第 1 步:定义类参数
lib/common/widgets/text_form.dart
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 
 | class TextFormWidget extends StatefulWidget {
 
 final TextEditingController? controller;
 
 
 final InputDecoration? decoration;
 
 
 final String? Function(String?)? validator;
 
 
 final bool? autofocus;
 
 
 final String? labelText;
 
 
 final bool? isMustBeEnter;
 
 
 final bool? isObscure;
 
 
 final bool? readOnly;
 
 
 final TextInputType? keyboardType;
 
 
 final List<TextInputFormatter>? inputFormatters;
 
 
 final String? hintText;
 
 
 final Function()? onTap;
 
 const TextFormWidget({
 Key? key,
 this.controller,
 this.autofocus = false,
 this.labelText,
 this.isMustBeEnter = false,
 this.validator,
 this.isObscure = false,
 this.decoration,
 this.keyboardType,
 this.inputFormatters,
 this.readOnly = false,
 this.onTap,
 this.hintText,
 }) : super(key: key);
 
 @override
 _TextFormWidgetState createState() => _TextFormWidgetState();
 }
 
 | 
第 2 步:build 函数
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 
 | class _TextFormWidgetState extends State<TextFormWidget> {
 bool _isShowObscureIcon = false;
 
 @override
 void initState() {
 super.initState();
 _isShowObscureIcon = widget.isObscure!;
 }
 
 @override
 Widget build(BuildContext context) {
 return TextFormField(
 onTap: widget.onTap,
 readOnly: widget.readOnly!,
 autofocus: widget.autofocus!,
 keyboardType: widget.keyboardType,
 controller: widget.controller,
 decoration: widget.isObscure == true
 ? InputDecoration(
 hintText: widget.hintText,
 
 labelText: widget.isMustBeEnter == true
 ? "* ${widget.labelText}"
 : widget.labelText,
 
 suffixIcon: IconButton(
 onPressed: () {
 setState(() {
 _isShowObscureIcon = !_isShowObscureIcon;
 });
 },
 icon: Icon(
 _isShowObscureIcon == true
 ? Icons.visibility
 : Icons.visibility_off,
 size: 15,
 color: AppColors.surfaceVariant,
 ),
 ),
 )
 : InputDecoration(
 hintText: widget.hintText,
 labelText: widget.isMustBeEnter == true
 ? "* ${widget.labelText}"
 : widget.labelText,
 ),
 
 validator: widget.validator,
 
 obscureText: _isShowObscureIcon,
 
 inputFormatters: widget.inputFormatters,
 );
 }
 }
 
 | 
第 3 步:调试界面
lib/pages/styles/styles_index/view.dart
| 12
 3
 4
 5
 
 | ListTile(
 onTap: () => Get.toNamed(RouteNames.stylesTextForm),
 title: const TextWidget.body1("form 表单"),
 ),
 
 | 
lib/pages/styles/text_form/controller.dart
| 12
 3
 4
 
 | GlobalKey formKey = GlobalKey<FormState>();
 TextEditingController unameController = TextEditingController(text: "ducafecat");
 TextEditingController pwdController = TextEditingController(text: "123456");
 
 | 
| 12
 3
 4
 5
 6
 
 | @overridevoid onClose() {
 super.onClose();
 unameController.dispose();
 pwdController.dispose();
 }
 
 | 
lib/pages/styles/text_form/view.dart
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 
 | Widget _buildTextForm() {
 return Form(
 key: controller.formKey,
 autovalidateMode: AutovalidateMode.onUserInteraction,
 child: <Widget>[
 TextFormWidget(
 
 keyboardType: TextInputType.emailAddress,
 controller: controller.unameController,
 labelText: "email",
 
 
 
 
 
 
 
 
 
 
 ),
 TextFormWidget(
 controller: controller.pwdController,
 labelText: "password",
 isObscure: true,
 
 
 
 
 
 
 
 
 
 ).marginOnly(
 bottom: 10,
 ),
 ButtonWidget.primary(
 "submit",
 onTap: () {
 if ((controller.formKey.currentState as FormState).validate()) {
 try {} finally {}
 }
 },
 ).tight(width: 100, height: 40),
 ].toColumn());
 }
 
 
 Widget _buildView() {
 return SingleChildScrollView(
 child: _buildTextForm().padding(
 all: AppSpace.page,
 ),
 );
 }
 
 | 
最后:运行
 
提交代码到 git