Skip to main content

构建带验证的表单

应用程序通常需要用户在文本字段中输入信息。例如,您可能需要用户使用电子邮件地址和密码组合登录。

为了使应用程序安全且易于使用,请检查用户提供的信息是否有效。如果用户正确填写了表单,则处理信息。如果用户提交了不正确的信息,则显示友好的错误消息,让他们知道出了什么问题。

在此示例中,学习如何使用以下步骤向具有单个文本字段的表单添加验证:

  1. 使用 GlobalKey 创建一个 Form
  2. 添加具有验证逻辑的 TextFormField
  3. 创建一个按钮来验证和提交表单。

1. 使用 GlobalKey 创建 Form

#

创建一个 FormForm 小部件充当分组和验证多个表单字段的容器。

创建表单时,请提供 GlobalKey。这会为您的 Form 分配一个唯一标识符。它还允许您稍后验证表单。

将表单创建为 StatefulWidget。这允许您只创建一次唯一的 GlobalKey<FormState>()。然后,您可以将其存储为变量并在不同位置访问它。

如果您将其设置为 StatelessWidget,则需要将此键存储 在某个地方。由于它资源密集型,您不希望每次运行 build 方法时都生成一个新的 GlobalKey

dart
import 'package:flutter/material.dart';

// 定义一个自定义 Form 小部件。
class MyCustomForm extends StatefulWidget {
  const MyCustomForm({super.key});

  @override
  MyCustomFormState createState() {
    return MyCustomFormState();
  }
}

// 定义相应的 State 类。
// 此类保存与表单相关的数据。
class MyCustomFormState extends State<MyCustomForm> {
  // 创建一个全局键,该键唯一标识 Form 小部件
  // 并允许验证表单。
  //
  // 注意:这是一个 `GlobalKey<FormState>`,
  // 不是 GlobalKey<MyCustomFormState>。
  final _formKey = GlobalKey<FormState>();

  @override
  Widget build(BuildContext context) {
    // 使用上面创建的 _formKey 构建 Form 小部件。
    return Form(
      key: _formKey,
      child: const Column(
        children: <Widget>[
          // 在此处添加 TextFormFields 和 ElevatedButton。
        ],
      ),
    );
  }
}

2. 添加具有验证逻辑的 TextFormField

#

虽然 Form 已就位, 但它没有提供用户输入文本的方式。这是 TextFormField 的作用。TextFormField 小部件呈现材料设计文本字段,并在出现验证错误时可以显示这些错误。

通过向 TextFormField 提供 validator() 函数来验证输入。如果用户的输入无效,则 validator 函数返回包含错误消息的 String。如果没有错误,则验证器必须返回 null。

在此示例中,创建一个 validator 来确保 TextFormField 不为空。如果为空,则返回友好的错误消息。

dart
TextFormField(
  // 验证器接收用户输入的文本。
  validator: (value) {
    if (value == null || value.isEmpty) {
      return '请输入一些文本';
    }
    return null;
  },
),

3. 创建一个按钮来验证和提交表单

#

现在您已经有了一个带有文本字段的表单, 提供一个按钮,用户可以点击该按钮来提交信息。

当用户尝试提交表单时,检查表单是否有效。如果有效,则显示成功消息。如果无效(文本字段没有内容),则显示错误消息。

dart
ElevatedButton(
  onPressed: () {
    // 如果表单有效,则 Validate 返回 true,否则返回 false。
    if (_formKey.currentState!.validate()) {
      // 如果表单有效,则显示一个 SnackBar。在现实世界中,
      // 您通常会调用服务器或将信息保存在数据库中。
      ScaffoldMessenger.of(context).showSnackBar(
        const SnackBar(content: Text('正在处理数据')),
      );
    }
  },
  child: const Text('提交'),
),

它是如何工作的?

#

要验证表单,请使用步骤 1 中创建的 _formKey。您可以使用 _formKey.currentState 访问器来访问 FormState,Flutter 在构建 Form 时会自动创建它。

FormState 类包含 validate() 方法。当调用 validate() 方法时,它会为表单中的每个文本字段运行 validator() 函数。如果一切看起来都很好,则 validate() 方法返回 true。如果任何文本字段包含错误,则 validate() 方法会重建表单以显示任何错误消息并返回 false

交互式示例

#
import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    const appTitle = '表单验证演示';

    return MaterialApp(
      title: appTitle,
      home: Scaffold(
        appBar: AppBar(
          title: const Text(appTitle),
        ),
        body: const MyCustomForm(),
      ),
    );
  }
}

// 创建一个 Form 小部件。
class MyCustomForm extends StatefulWidget {
  const MyCustomForm({super.key});

  @override
  MyCustomFormState createState() {
    return MyCustomFormState();
  }
}

// 创建相应的 State 类。
// 此类保存与表单相关的数据。
class MyCustomFormState extends State<MyCustomForm> {
  // 创建一个全局键,该键唯一标识 Form 小部件
  // 并允许验证表单。
  //
  // 注意:这是一个 GlobalKey<FormState>,
  // 不是 GlobalKey<MyCustomFormState>。
  final _formKey = GlobalKey<FormState>();

  @override
  Widget build(BuildContext context) {
    // 使用上面创建的 _formKey 构建 Form 小部件。
    return Form(
      key: _formKey,
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          TextFormField(
            // 验证器接收用户输入的文本。
            validator: (value) {
              if (value == null || value.isEmpty) {
                return '请输入一些文本';
              }
              return null;
            },
          ),
          Padding(
            padding: const EdgeInsets.symmetric(vertical: 16),
            child: ElevatedButton(
              onPressed: () {
                // 如果表单有效,则 Validate 返回 true,否则返回 false。
                if (_formKey.currentState!.validate()) {
                  // 如果表单有效,则显示一个 SnackBar。在现实世界中,
                  // 您通常会调用服务器或将信息保存在数据库中。
                  ScaffoldMessenger.of(context).showSnackBar(
                    const SnackBar(content: Text('正在处理数据')),
                  );
                }
              },
              child: const Text('提交'),
            ),
          ),
        ],
      ),
    );
  }
}

要了解如何检索这些值,请查看 检索文本字段的值 食谱。