前言

最近在利用flutter制作校园软件,需要制作一个登录界面,所以要用到Flutter中的一些表单控件,今天就来总结下flutter中的一些表单控件。 本文参考:

TextField, FormField

基本属性

先从最基础的讲起,对于TextField就是android中的edittext,就是一个输入框( TextField class),这个输入框常用的属性如下:

child: new TextField(
autocorrect: false, // 是否自动校正
autofocus: false, //自动获取焦点
enabled: true, // 是否启用
inputFormatters: [], //对输入的文字进行限制和校验
keyboardType: TextInputType.text, //获取焦点时,启用的键盘类型
maxLines: 2, // 输入框最大的显示行数
maxLength: 3, //允许输入的字符长度/
maxLengthEnforced: false, //是否允许输入的字符长度超过限定的字符长度
obscureText: true, // 是否隐藏输入的内容
onChanged: (newValue) {
    // print(newValue); // 当输入内容变更时,如何处理
},
onSubmitted: (value) {
    // print("whar"); // 当用户确定已经完成编辑时触发
},
style: new TextStyle(
    color: new Color(Colors.amberAccent.green)), // 设置字体样式
textAlign: TextAlign.center, //输入的内容在水平方向如何显示
decoration: new InputDecoration(
    labelText: "城市",
    icon: new Icon(Icons.location_city),
    border: new OutlineInputBorder(), // 边框样式
    helperText: 'required',
    hintText: '请选择你要投保的城市',
    prefixIcon: new Icon(Icons.android),
    prefixText: 'Hello'),
),

输入处理

其实对于一个输入框,我们最关心的无非就是监听输入的内容,然后输入完成后,输入框中的内容是什么,文档中写的很清楚,textfiled控件有三个回调函数: 在这里我们只需要关注onChangedonSubmitted即可。

child: new TextField(
    controller: _controller,
    decoration: new InputDecoration(labelText: 'Your Name'),
    onChanged: (val) {
        print(val);
    },
    onSubmitted: (String v) {
        print(v);
    },
),

顾名思义: onChanged 事件,在输入内容发生变化的时候触发,onSubmitted事件,则是在输入结束,点击完成的时候触发。 然而在TextFormField中没有这两个事件,取而代之的是validator,onSaved,onFieldSubmitted 他们都接受三个函数,并且将其值作为参数传递到函数里面

  • validator,如果开启autovalidate: true,那么将会自动检验输入的值,如果没有则会在表单提交的时候检验 该函数只允许返回验证失败的错误信息以及验证通过时返回null。
  • onSaved, 当调用FormState.save方法的时候调用。
  • onFieldSubmitted, 与onSubmitted一样,则是在输入结束,点击完成的时候触发。

编辑控制

无论是在TextField还是TextFormField中,都有一个重要的属性controller,该属性可用来对输入框内容进行控制。 先创建一个控制对象:

 TextEditingController _controller = new TextEditingController();
 TextEditingController _formFieldController = new TextEditingController();

为输入框初始化值以及注册一个监听事件:

 @override
  void initState() {
    // TODO: implement initState
    super.initState();
    _controller.value = new TextEditingValue(text: 'Hello');
    _formFieldController.addListener(() {
      print('listener');
    });
  }

触发一个监听事件:

 void _textFieldAction() {
    // print(_formFieldController.selection);
    // print(_formFieldController.text); //获取输入内容
    print(_formFieldController.hasListeners); //判断是否注册监听事件
    _formFieldController.notifyListeners(); //触发监听事件
  }

Form

Flutter中的Form组件和html中的<form></form>的作用类似,都是起到了一个容器的作用,里面包含了TextFormField的一个列表 下面通过一个例子说明表单的一些特性

  1. 布局
@override
  Widget build(BuildContext context) {
    // TODO: implement build
    return new MaterialApp(
      title: 'Flutter data',
      home: new Scaffold(
        appBar: new AppBar(
          title: new Text('Flutter Form'),
        ),
        floatingActionButton: new FloatingActionButton(
          onPressed: _forSubmitted,
          child: new Text('提交'),
        ),
        body: new Container(
          padding: const EdgeInsets.all(16.0),
          child: new Form(
            key: _formKey,
            child: new Column(
              children: <Widget>[
                new TextFormField(
                  decoration: new InputDecoration(
                    labelText: 'Your Name',
                  ),
                  onSaved: (val) {
                    _name = val;
                  },
                ),
                new TextFormField(
                  decoration: new InputDecoration(
                    labelText: 'Password',
                  ),
                  obscureText: true,
                  validator: (val) {
                    return val.length < 4 ? "密码长度错误" : null;
                  },
                  onSaved: (val) {
                    _password = val;
                  },
                ),
              ],
            ),
          ),
        ),
      ),
    );

以上,我们使用一个Form包裹着两个TextFormField组件,在这里为了简便,我们只设置了一些必要的元素,先暂时忽略TextFormField中的事件 为了获取表单的实例,我们需要设置一个全局类型的key,通过这个key的属性,来获取表单对象。

GlobalKey<FormState> _formKey = new GlobalKey<FormState>();
String _name;
String _password;

同时也设置了_name,_password两个变量来存储用户的输入值,在TextFormField组件的onSaved方法中,将输入框的值赋值到设定的变量中 我们通过FloatingActionButton来触发表单提交事件,

floatingActionButton: new FloatingActionButton(
    onPressed: _forSubmitted,
    child: new Text('提交'),
),

_forSubmitted中我们使用keycurrentState属性来获取表单的实例对象

 void _forSubmitted() {
    var _form = _formKey.currentState;

    if (_form.validate()) {
      _form.save();
      print(_name);
      print(_password);
    }
  }

对于表单对象来说,其有一些非常实用的方法比如: reset 重置表单内容 validate, 调用TextFormFieldvalidator方法 save, 表单保存。

完整代码

import 'package:flutter/material.dart';

void main() => runApp(new HomePage());

class HomePage extends StatefulWidget {
  @override
  _HomePageState createState() => new _HomePageState();
}

class _HomePageState extends State<HomePage> {
  GlobalKey<FormState> _formKey = new GlobalKey<FormState>();

  String _name;

  String _password;

  void _forSubmitted() {
    var _form = _formKey.currentState;

    if (_form.validate()) {
      _form.save();
      print(_name);
      print(_password);
    }
  }

  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return new MaterialApp(
      title: 'Flutter data',
      home: new Scaffold(
        appBar: new AppBar(
          title: new Text('Flutter Form'),
        ),
        floatingActionButton: new FloatingActionButton(
          onPressed: _forSubmitted,
          child: new Text('提交'),
        ),
        body: new Container(
          padding: const EdgeInsets.all(16.0),
          child: new Form(
            key: _formKey,
            child: new Column(
              children: <Widget>[
                new TextFormField(
                  decoration: new InputDecoration(
                    labelText: 'Your Name',
                  ),
                  onSaved: (val) {
                    _name = val;
                  },
                ),
                new TextFormField(
                  decoration: new InputDecoration(
                    labelText: 'Password',
                  ),
                  obscureText: true,
                  validator: (val) {
                    return val.length < 4 ? "密码长度错误" : null;
                  },
                  onSaved: (val) {
                    _password = val;
                  },
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }
}