Flutter 常用Widget-输入框

Material design组件提供了两种输入框,分别是TextField和TextFormField。他们的作用都是使用户可以使用硬件键盘或屏幕键盘输入文本。

TextField

每当用户更改字段中的文本时,文本字段就会调用onChanged回调。如果用户已完成在字段中的键入(例如,通过按软键盘上的按钮),则文本字段将调用onSubmitted回调。

要控制在文本字段中显示的文本,就要使用controller。例如,要设置文本字段的初始值,请使用已经包含一些文本的controller。

默认情况下,TextField具有默认修饰,该修饰在TextField下方绘制分隔线。您可以使用decoration属性来控制装饰,例如,通过添加标签或图标。如果将decoration属性设置为null,则装饰将被完全删除。

如果装饰非空(这是默认值),则TextField要求其父节点是material widget。轻击TextField时,触发涟漪效果。

要将TextField与其他FormField集成到Form中,请考虑使用TextFormField。

 

TextFormField

TextFormField继承FormField包含一个TextField。TextFormField使得重置或验证多个字段变得更加容易。 要在没有表单的情况下使用,请将GlobalKey传递给构造函数,然后使用GlobalKey.currentState保存或重置表单字段。

指定controller后,TextEditingController.text定义initialValue。 如果FormField是延迟构造其子级的滚动容器的一部分,例如ListView或CustomScrollView,则应指定一个控制器。 控制器的生存期应由滚动容器的有状态widget父节点管理。

如果未指定控制器,则可以使用initialValue为自动生成的控制器提供初始值。

 

Controller

我们在来看看controller,通过它可以设置/获取编辑框的内容、选择编辑内容、监听编辑文本改变事件。大多数情况下我们都需要显式提供一个controller来与文本框交互。如果没有提供controller,则TextField内部会自动创建一个。

class TextFieldPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Padding(
          padding: const EdgeInsets.all(8.0),
          child: TextField(
            onChanged: (value) {
              print("value $value");
            },
            decoration: InputDecoration(
              labelText: "请输入用户名",
              hintText: "我是暗示",
              prefixIcon: Icon(Icons.person),
            ),
          ),
        ),
      ),
    );
  }
}

 

获取输入内容

  • onChange 上面的代码中已经使用了这个办法
  • controller 
// 创建controller
TextEditingController _controller = TextEditingController();
_controller.text="我是默认值";
// 设置controller
TextField(
  controller: _selectionController,
)

我们来看完整代码

class TextFieldPage extends StatelessWidget {
  final TextEditingController _controller = TextEditingController();
  TextFieldPage() {
    _controller.addListener(() {
      print(_controller.text);
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Padding(
          padding: const EdgeInsets.all(8.0),
          child: TextField(
            controller: _controller,
            onChanged: (value) {
              print("value $value");
            },
            decoration: InputDecoration(
              labelText: "请输入用户名",
              hintText: "我是暗示",
              prefixIcon: Icon(Icons.person),
            ),
          ),
        ),
      ),
    );
  }
}

两种方式相比,onChanged是专门用于监听文本变化,而controller的功能却多一些,比如设置默认值、选择文本等。

 

对于输入框,我们在开发中可能最关心的还是输入的内容是否合法,比如电话号是否合法,邮箱是否合法等。这个时候就要用到我们的表单Form 和 TextFormField了。

Form组件主要属性

属性类型说明
keyKeyWidget树中的key
autovalidatebool自动提交表单
childWidget组件的child
onChanged

VoidCallback

当FormField值改变回调函数
.........

 

 

 

 

 

 

 

TextFormField主要属性

属性类型说明
keyKeyWidget树中的key
autovalidatebool自动验证
initialValueT初始值
onSavedFormFieldSetter<T>Form调用保存方法回调
validatorFormFieldValidator<T>Form表单验证
.........

 

 

 

 

 

 

 

 

要想获得表单,我们需要设置一个全局类型的key,通过这个key的属性来获取表单对象。关于key,我会在另外的文章中介绍。

class TextFieldPage extends StatelessWidget {
  final GlobalKey<FormState> _globalKey = GlobalKey<FormState>();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          children: [
            Form(
              key: _globalKey,
              child: TextFormField(
                onSaved: (value) {
                  print("onSaved $value");
                },
                validator: (value) {
                  print("onSaved $value");
                  return value.length < 4 ? "长度不够" : null;
                },
                decoration: InputDecoration(
                  labelText: "请输入用户名",
                  hintText: "我是暗示",
                  prefixIcon: Icon(Icons.person),
                ),
              ),
            ),
            RaisedButton(
              child: Text('登陆'),
              onPressed: () {
                if (_globalKey.currentState.validate()) {
                  print('登陆成功');
                }
              },
            ),
          ],
        ),
      ),
    );
  }
}

 

整理一下,这里使用了Form,FormField,FormState

  • Form继承自StatefulWidget对象,它对应的状态类为FormState。
  • FormStateFormState类,可以通过Form.of()GlobalKey获得。我们可以通过它来对Form的子FormField进行统一操作。
  • FormField是一个抽象类,定义几个属性,FormState内部通过它们来完成操作。TextFormField继承FormField。也是TextField的一个包装类,所以除了FormField定义的属性之外,它还包括TextField的属性。

值得注意的是,如果使用Form.of()来获得FormState需要在Form的子节点中,包含一层Builder参数,此时返回的context才是可以获取到父节点的context。

总结:今天介绍了如何使用TextField或者Form加TextFormField来实现输入框功能,controller以及一些基本的回调函数,还要注意使用Form的表单的获取方式等。接下来的文章会继续将常用Widget逐一介绍,在最后的系列中,会公开一个商业级的项目,感兴趣的小伙伴关注。如果您在阅读过程中发现错误,请及时留言给我,我会第一时间改正。也欢迎大家一切交流,共同进步,感谢支持!

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值