表格交互实用教程 | 构建一个有验证判断的表单

应用程序通常会要求用户在文本框中输入信息。例如,我们可能正在开发一个应用程序,该应用程序就需要用户输入邮箱和密码登录。

为了让应用程序更为安全易用,我们通常都需要验证用户输入的信息是否有效。如果用户输入了正确的信息,就可以针对该信息进行后续处理。如果用户输入了错误的信息,就需要在相关的输入区域展示一条输入信息出错的提示,以便用户更正输入。

你可以通过以下步骤,在下面的例子中学习如何为表单中的文本输入框加入验证判断的功能:

步骤

  1. 创建表单 Form,并以 GlobalKey 作为唯一性标识2. 添加带验证逻辑的 TextFormField 到表单中3. 创建按钮以验证和提交表单1. 创建表单 Form,并以 GlobalKey 作为唯一性标识

首先,我们需要创建一个表单组件 Form 作为容器承载和验证多个表单域。

当我们创建表单 Form 的时候,需要提供一个 GlobalKeyGlobalKey 唯一标识了这个表单 Form,在后续的表单验证步骤中,也起到了关键的作用。

// Define a custom Form widget.

class MyCustomForm extends StatefulWidget {

  @override

  MyCustomFormState createState() {

    return MyCustomFormState();

  }

}



// Define a corresponding State class.

// This class holds data related to the form.

class MyCustomFormState extends State<MyCustomForm> {

  // Create a global key that uniquely identifies the Form widget

  // and allows validation of the form.

  //

  // Note: This is a `GlobalKey<FormState>`,

  // not a GlobalKey<MyCustomFormState>.

  final _formKey = GlobalKey<FormState>();



  @override

  Widget build(BuildContext context) {

    // Build a Form widget using the _formKey created above.

    return Form(

      key: _formKey,

      child: // Build this out in the next steps.

    );

  }

}

<aside class="alert alert-success" role="alert" style="margin-bottom: 1rem;padding: 1.5rem;white-space: normal;box-sizing: border-box;border-width: 1px;border-style: solid;border-color: rgb(195, 230, 203);border-radius: 0px;color: rgb(21, 87, 36);background-color: rgb(212, 237, 218);font-family: "Noto Sans SC", "Helvetica Neue", Helvetica, Arial, "PingFang SC", "Hiragino Sans GB", "Heiti SC", "Microsoft YaHei", "WenQuanYi Micro Hei", sans-serif;font-size: 16px;text-align: left;">
小提示

一般情况下,推荐使用 GlobalKey 来访问一个表单。嵌套组件且组件树比较复杂的情况下,可以使用 Form.of() 方法访问表单。

**2. 添加带验证逻辑的 TextFormField 到表单中**

尽管在前面步骤中,已经创建出表单 Form 了,但我们此时还需要提供一个 TextFormField 让用户输入文本信息。TextFormField是遵循 material 设计风格的文本输入框,并且能够在输入验证不通过时显示错误提醒。

通过给 TextFormField 加入 validator() 函数可以验证输入是否正确。validator 函数会校验用户输入的信息,如果信息有误,会返回包含出错原因的字符串 String。如果信息无误,则不返回。

在下面的实例中,我们会在 TextFormField 中加入一个 validator 验证函数,它的功能是判断用户输入的文本是否为空,如果为空,就返回「请输入文本」的友情提示。

TextFormField(

  // The validator receives the text that the user has entered.

  validator: (value) {

    if (value.isEmpty) {

      return 'Enter some text';

    }

    return null;

  },

);

3. 创建按钮以验证和提交表单

在创建完表单以及文本框后,还需要提供一个按钮让用户提交表单。

当用户提交表单后,我们会预先检查表单信息是否有效。如果文本框有内容,表单有效,则会显示正确信息。如果文本框没有输入任何内容,表单无效,会在文本框区域展示错误提示。

RaisedButton(

  onPressed: () {

    // Validate returns true if the form is valid, otherwise false.

    if (_formKey.currentState.validate()) {

      // If the form is valid, display a snackbar. In the real world,

      // you'd often call a server or save the information in a database.



      Scaffold

          .of(context)

          .showSnackBar(SnackBar(content: Text('Processing Data')));

    }

  },

  child: Text('Submit'),

);

实现原理

为了验证表单,我们需要使用到步骤 1 中的 _formKey。使用 _formKey.currentState() 方法去访问 FormState,而 FormState是在创建表单 Form 时 Flutter 自动生成的。

FormState 类包含了 validate() 方法。当 validate() 方法被调用的时候,会遍历运行表单中所有文本框的 validator() 函数。如果所有 validator() 函数验证都通过,validate() 方法返回 true。如果有某个文本框验证不通过,就会在那个文本框区域显示错误提示,同时 validate() 方法返回 false

完整样例

import 'package:flutter/material.dart';



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



class MyApp extends StatelessWidget {

  @override

  Widget build(BuildContext context) {

    final appTitle = 'Form Validation Demo';



    return MaterialApp(

      title: appTitle,

      home: Scaffold(

        appBar: AppBar(

          title: Text(appTitle),

        ),

        body: MyCustomForm(),

      ),

    );

  }

}



// Create a Form widget.

class MyCustomForm extends StatefulWidget {

  @override

  MyCustomFormState createState() {

    return MyCustomFormState();

  }

}



// Create a corresponding State class.

// This class holds data related to the form.

class MyCustomFormState extends State<MyCustomForm> {

  // Create a global key that uniquely identifies the Form widget

  // and allows validation of the form.

  //

  // Note: This is a GlobalKey<FormState>,

  // not a GlobalKey<MyCustomFormState>.

  final _formKey = GlobalKey<FormState>();



  @override

  Widget build(BuildContext context) {

    // Build a Form widget using the _formKey created above.

    return Form(

      key: _formKey,

      child: Column(

        crossAxisAlignment: CrossAxisAlignment.start,

        children: <Widget>[

          TextFormField(

            validator: (value) {

              if (value.isEmpty) {

                return 'Enter some text';

              }

              return null;

            },

          ),

          Padding(

            padding: const EdgeInsets.symmetric(vertical: 16.0),

            child: RaisedButton(

              onPressed: () {

                // Validate returns true if the form is valid, or false

                // otherwise.

                if (_formKey.currentState.validate()) {

                  // If the form is valid, display a Snackbar.

                  Scaffold.of(context)

                      .showSnackBar(SnackBar(content: Text('Processing Data')));

                }

              },

              child: Text('Submit'),

            ),

          ),

        ],

      ),

    );

  }

}

最多阅读

在Flutter中添加资源和图片 1年以前  |  1945次阅读
发布Flutter开发的iOS程序 1年以前  |  1367次阅读
Flutter Widget框架概述 1年以前  |  1194次阅读
在Flutter中发起HTTP网络请求 1年以前  |  1137次阅读
JSON和序列化 1年以前  |  1068次阅读
使用Inspector检查用户界面 1年以前  |  1049次阅读
Flutter的手势GestureDetector分析详解 9月以前  |  1013次阅读
Flutter框架概览 1年以前  |  1004次阅读
为Flutter应用程序添加交互 1年以前  |  971次阅读
使用自定义字体 1年以前  |  968次阅读
Flutter插件详解及其发布插件 8月以前  |  961次阅读
处理文本输入 1年以前  |  854次阅读
Flutter 状态管理指南之 Provider 9月以前  |  788次阅读
发布Flutter开发的Android程序 1年以前  |  780次阅读
使用包来开发Flutter应用 1年以前  |  777次阅读
编写国际化Flutter App 1年以前  |  758次阅读
Dart 语法预览 1年以前  |  732次阅读
使用平台通道编写平台特定的代码 1年以前  |  721次阅读
Flutter路由详解 9月以前  |  688次阅读