【Flutter】十、Flutter之表单——Form

Form作为一个容器,可包裹多个表单字段(FormField)。FormField是一个抽象类,TextFormText是FormField的一个实现类,因此可以在Form中使用TextFormField。

一、Form

1.1 Form构造器

const Form({
    Key key,
    @required this.child,
    this.autovalidate = false,
    this.onWillPop,
    this.onChanged,
  }) : assert(child != null),
       super(key: key);

1.2 Form属性说明

属性说明
Widget child孩子节点
bool autovalidate是否自动验证,如果为true,表单字段将在每次更改后立即验证和更新其错误文本;如果为false,则需要调用FormState.validate进行验证。
WillPopCallback onWillPop决定Form所在的路由是否可以直接返回(如点击返回按钮),该回调返回一个Future对象,如果Future的最终结果是false,则当前路由不会返回;如果为true,则会返回到上一个路由。此属性通常用于拦截返回按钮
VoidCallback onChangedForm的任意一个子FormField内容发生变化时会触发此回调

二、TextFormField

2.1 TextFormField构造器

TextFormField({
    Key key,
    this.controller,
    String initialValue,
    FocusNode focusNode,
    InputDecoration decoration = const InputDecoration(),
    TextInputType keyboardType,
    TextCapitalization textCapitalization = TextCapitalization.none,
    TextInputAction textInputAction,
    TextStyle style,
    StrutStyle strutStyle,
    TextDirection textDirection,
    TextAlign textAlign = TextAlign.start,
    bool autofocus = false,
    bool readOnly = false,
    bool showCursor,
    bool obscureText = false,
    bool autocorrect = true,
    bool autovalidate = false,
    bool maxLengthEnforced = true,
    int maxLines = 1,
    int minLines,
    bool expands = false,
    int maxLength,
    VoidCallback onEditingComplete,
    ValueChanged<String> onFieldSubmitted,
    FormFieldSetter<String> onSaved,
    FormFieldValidator<String> validator,
    List<TextInputFormatter> inputFormatters,
    bool enabled = true,
    double cursorWidth = 2.0,
    Radius cursorRadius,
    Color cursorColor,
    Brightness keyboardAppearance,
    EdgeInsets scrollPadding = const EdgeInsets.all(20.0),
    bool enableInteractiveSelection = true,
    InputCounterWidgetBuilder buildCounter,
  }) : assert(initialValue == null || controller == null),
       assert(textAlign != null),
       assert(autofocus != null),
       assert(readOnly != null),
       assert(obscureText != null),
       assert(autocorrect != null),
       assert(autovalidate != null),
       assert(maxLengthEnforced != null),
       assert(scrollPadding != null),
       assert(maxLines == null || maxLines > 0),
       assert(minLines == null || minLines > 0),
       assert(
         (maxLines == null) || (minLines == null) || (maxLines >= minLines),
         'minLines can\'t be greater than maxLines',
       ),
       assert(expands != null),
       assert(
         !expands || (maxLines == null && minLines == null),
         'minLines and maxLines must be null when expands is true.',
       ),
       assert(maxLength == null || maxLength > 0),
       assert(enableInteractiveSelection != null),
       super(
    key: key,
    initialValue: controller != null ? controller.text : (initialValue ?? ''),
    onSaved: onSaved,
    validator: validator,
    autovalidate: autovalidate,
    enabled: enabled,
    builder: (FormFieldState<String> field) {
      final _TextFormFieldState state = field;
      final InputDecoration effectiveDecoration = (decoration ?? const InputDecoration())
        .applyDefaults(Theme.of(field.context).inputDecorationTheme);
      return TextField(
        controller: state._effectiveController,
        focusNode: focusNode,
        decoration: effectiveDecoration.copyWith(errorText: field.errorText),
        keyboardType: keyboardType,
        textInputAction: textInputAction,
        style: style,
        strutStyle: strutStyle,
        textAlign: textAlign,
        textDirection: textDirection,
        textCapitalization: textCapitalization,
        autofocus: autofocus,
        readOnly: readOnly,
        showCursor: showCursor,
        obscureText: obscureText,
        autocorrect: autocorrect,
        maxLengthEnforced: maxLengthEnforced,
        maxLines: maxLines,
        minLines: minLines,
        expands: expands,
        maxLength: maxLength,
        onChanged: field.didChange,
        onEditingComplete: onEditingComplete,
        onSubmitted: onFieldSubmitted,
        inputFormatters: inputFormatters,
        enabled: enabled,
        cursorWidth: cursorWidth,
        cursorRadius: cursorRadius,
        cursorColor: cursorColor,
        scrollPadding: scrollPadding,
        keyboardAppearance: keyboardAppearance,
        enableInteractiveSelection: enableInteractiveSelection,
        buildCounter: buildCounter,
      );
    },
  );

从TextFormField的构造函数中可以看出,builder返回了一个TextField,所以对于TextFormField的属性参考TextField即可;由于TextFormField继承自FormField,所以FormField的属性TextFormField也可以使用,具体说明参考如下。

2.2 TextFormField部分属性说明

属性说明
FormFieldSetter onSaved保存回调,调用FormState.save的回调
FormFieldValidator validator验证回调,如果开启autovalidate: true,那么将会自动检验输入的值,如果没有则会在表单提交的时候检验(FormState.validate),该函数只允许返回验证失败的错误信息以及验证通过时返回null。
T initialValue初始值
bool autovalidate是否自动校验
bool enabled是否可用

三、FormState

FormState为Form的State类,可以通过Form.of()或GlobalKey获得。我们可以通过它来对Form的子孙FormField进行统一操作。

  1. FormState.validate():调用此方法后,会调用Form子孙FormField的validate回调,如果有一个校验失败,则返回false,所有校验失败项都会返回用户返回的错误提示。
  2. FormState.save():调用此方法后,会调用Form子孙FormField的save回调,用于保存表单内容
  3. FormState.reset():调用此方法后,会将子孙FormField的内容清空,清空不会清空初始值。

示例

下面是一个用户登录表单,满足以下条件:

  1. 用户名不为空
  2. 密码长度大于6位
  3. 可清空
import 'package:flutter/material.dart';

class FormDemo extends StatelessWidget{
  final _formKey = GlobalKey<FormState>();

  @override
  Widget build(BuildContext context) {
    return Form(
      key: _formKey,
      autovalidate: false,
      onChanged: (){
        print('change');
      },
      child: Padding(
        padding:const EdgeInsets.all(20.0),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.center,
          children: <Widget>[
            TextFormField(
              decoration: InputDecoration(
                icon: Icon(Icons.person_outline),
                labelText: '用户名'
              ),
              validator: (value) {
                return value.isEmpty ? '用户名不能为空' : null;
              },
              onSaved: (data){
                print('save:$data');
              },
              initialValue: 'user',
              autovalidate: false,
              enabled: true,
            ),
            TextFormField(
              decoration: InputDecoration(
                icon:Icon(Icons.lock_outline),
                labelText: '密码',
              ),
              obscureText: true,
              validator: (value){
                if (value.isEmpty) {
                  return '密码不能为空';
                }
                if (value.length <= 6) {
                  return '密码不能低于6位';
                }
                return null;
              },
            ),
            Padding(
                padding: const EdgeInsets.symmetric(vertical: 8.0),
                child: Row(
                  children: <Widget>[
                    Expanded(
                      child: RaisedButton(
                        onPressed: () {
                          _formKey.currentState.reset();
                        },
                        child: Text('清空'),
                      ),
                    )
                  ],
                )
            ),
            Padding(
              padding: const EdgeInsets.symmetric(vertical: 8.0),
              child: Row(
                children: <Widget>[
                  Expanded(
                    child: RaisedButton(
                      color: Theme.of(context).primaryColor,
                      textColor: Colors.white,
                      onPressed: () {
                        if (_formKey.currentState.validate()) {
                          // Process data.
                        }
                      },
                      child: Text('登录'),
                    ),
                  )
                ],
              )
            ),
          ],
        ),
      )
    );
  }
}

在这里插入图片描述

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Flutter动态表单实现的一般步骤如下: 1. 定义表单字段数据模型:定义一个类来表示每个表单字段,包括字段类型、名称、值、是否必填等属性。 2. 构建表单UI:使用Flutter提供的表单控件,如TextFormField、Checkbox、Radio等来构建表单的UI。 3. 根据字段数据模型动态生成表单控件:根据表单字段数据模型动态生成相应的表单控件,可以使用Flutter的Widget库中的工厂方法来实现。 4. 收集表单数据:根据表单字段数据模型收集用户填写的表单数据,并进行校验处理。 5. 提交表单数据:将收集到的表单数据提交到服务器进行处理。 下面是一个简单的Flutter动态表单实现的示例代码: ```dart class FormField { final String label; final String type; final bool required; String value; FormField({ required this.label, required this.type, this.required = false, this.value = '', }); } class DynamicFormScreen extends StatefulWidget { @override _DynamicFormScreenState createState() => _DynamicFormScreenState(); } class _DynamicFormScreenState extends State<DynamicFormScreen> { final GlobalKey<FormState> _formKey = GlobalKey<FormState>(); List<FormField> _fields = [ FormField(label: 'Name', type: 'text', required: true), FormField(label: 'Email', type: 'email', required: true), FormField(label: 'Phone', type: 'tel', required: true), FormField(label: 'Message', type: 'textarea', required: false), ]; @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Dynamic Form'), ), body: Form( key: _formKey, child: ListView.builder( itemCount: _fields.length, itemBuilder: (BuildContext context, int index) { FormField field = _fields[index]; Widget widget; switch (field.type) { case 'text': case 'email': case 'tel': widget = TextFormField( decoration: InputDecoration( labelText: field.label, ), keyboardType: TextInputType.text, validator: (value) { if (field.required && value!.isEmpty) { return 'This field is required'; } return null; }, onSaved: (value) { field.value = value!; }, ); break; case 'textarea': widget = TextFormField( decoration: InputDecoration( labelText: field.label, ), keyboardType: TextInputType.multiline, maxLines: 4, validator: (value) { if (field.required && value!.isEmpty) { return 'This field is required'; } return null; }, onSaved: (value) { field.value = value!; }, ); break; default: widget = Container(); } return widget; }, ), ), floatingActionButton: FloatingActionButton( onPressed: () { if (_formKey.currentState!.validate()) { _formKey.currentState!.save(); // Submit form data } }, child: Icon(Icons.send), ), ); } } ``` 在上面的示例代码中,我们定义了一个FormField类来表示表单字段,包括字段名称、类型、是否必填以及字段值等属性。然后我们在StatefulWidget的状态类中定义了一个_fields列表来存储表单字段数据模型。在build方法中,我们使用ListView.builder来构建表单UI,根据表单字段数据模型动态生成相应的表单控件。最后,在提交按钮的点击事件中,我们根据表单字段数据模型收集用户填写的表单数据,并进行校验处理。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

MAXLZ

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值