flutter 表单

164 阅读2分钟

在 Flutter 中,表单是通过 FormTextFormField 等组件来构建的。表单可以用来收集用户输入,并且可以进行验证。下面是关于如何在 Flutter 中使用表单的基础介绍:

1. 创建一个简单的表单

首先,可以使用 Form 组件来包裹你的表单字段。 Form 组件提供了一个 FormState,可以帮助验证表单和保存表单数据。

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('Flutter Form Example')),
        body: MyCustomForm(),
      ),
    );
  }
}

class MyCustomForm extends StatefulWidget {
  @override
  _MyCustomFormState createState() => _MyCustomFormState();
}

class _MyCustomFormState extends State<MyCustomForm> {
  final _formKey = GlobalKey<FormState>();

  @override
  Widget build(BuildContext context) {
    return Form(
      key: _formKey,
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: <Widget>[
          TextFormField(
            decoration: InputDecoration(labelText: 'Enter your name'),
            validator: (value) {
              if (value == null || value.isEmpty) {
                return 'Please enter some text';
              }
              return null;
            },
          ),
          Padding(
            padding: const EdgeInsets.symmetric(vertical: 16.0),
            child: ElevatedButton(
              onPressed: () {
                // Validate returns true if the form is valid, otherwise false.
                if (_formKey.currentState!.validate()) {
                  ScaffoldMessenger.of(context)
                    .showSnackBar(SnackBar(content: Text('Processing Data')));
                }
              },
              child: Text('Submit'),
            ),
          ),
        ],
      ),
    );
  }
}

2. 验证表单

在上面的示例中,TextFormField 使用了 validator 参数来进行简单的验证。可以根据需要扩展验证逻辑,如验证邮箱格式、密码长度等。

2.1. 示例: 邮箱校验/整个表单校验

// 定义
final _formKey = GlobalKey<FormState>();

// 表单
Form(
  key: _formKey,
  child: Column(
    crossAxisAlignment: CrossAxisAlignment.start,
    children: <Widget>[
      TextFormField(
        controller: _controller.emailController,
        decoration: InputDecoration(
          labelText: 'signUpPage.email'.tr,
        ),
        keyboardType: TextInputType.emailAddress,
        validator: (value) {
          if (value == null || value.isEmpty) {
            return 'signUpPage.emailRequired'.tr;
          }
          if (!RegExp(r'^[^@]+@[^@]+.[^@]+').hasMatch(value)) {
            return 'signUpPage.emailVal'.tr;
          }
          return null;
        },
      ),
    ],
  ),
),

// 校验
if (_formKey.currentState?.validate() ?? false) {
  // 验证通过
}

单个字段校验

// 定义
final _emailFieldKey = GlobalKey<FormFieldState>();

// 表单
Form(
  key: _formKey,
  child: Column(
    crossAxisAlignment: CrossAxisAlignment.start,
    children: <Widget>[
      TextFormField(
        key: _emailFieldKey,
        controller: _controller.emailController,
        decoration: InputDecoration(
          labelText: 'signUpPage.email'.tr,
        ),
        keyboardType: TextInputType.emailAddress,
        validator: (value) {
          if (value == null || value.isEmpty) {
            return 'signUpPage.emailRequired'.tr;
          }
          if (!RegExp(r'^[^@]+@[^@]+.[^@]+').hasMatch(value)) {
            return 'signUpPage.emailVal'.tr;
          }
          return null;
        },
      ),
    ],
  ),
),

// 校验
if (_emailFieldKey.currentState?.validate() ?? false) {
  // 验证通过
}

3. 保存和重置表单

  • 保存表单数据:通过 FormState.save() 方法,可以保存表单中的输入数据。
  • 重置表单:使用 FormState.reset() 方法可以重置表单到初始状态。
ElevatedButton(
  onPressed: () {
    if (_formKey.currentState!.validate()) {
      _formKey.currentState!.save();
      // 保存数据逻辑
    }
  },
  child: Text('Save'),
),

ElevatedButton(
  onPressed: () {
    _formKey.currentState!.reset();
  },
  child: Text('Reset'),
),

4. 更多自定义字段

可以在表单中添加各种类型的输入字段,如 DropdownButtonFormFieldCheckboxFormField 等,来实现复杂的表单。

5. 使用控制器获取表单输入

可以使用 TextEditingController 来获取或设置 TextFormField 的值:

final TextEditingController _controller = TextEditingController();

TextFormField(
  controller: _controller,
  decoration: InputDecoration(labelText: 'Enter your email'),
),

// 获取输入值
String email = _controller.text;