前言

Material组件库中提供了输入框组件TextField和表单组件Form。

输入框TextField

接口描述

const TextField({
Key key,
// 编辑框的控制器,通过它可以设置/获取编辑框的内容、选择编辑内容、监听编辑文本改变事件。大多数情况下我们都需要显式提供一个controller来与文本框交互。如果没有提供controller,则TextField内部会自动创建一个。
this.controller,
// 用于控制TextField是否占有当前键盘的输入焦点。它是我们和键盘交互的一个句柄(handle)。
this.focusNode,
// 用于控制TextField的外观显示,如提示文本、背景颜色、边框等。
this.decoration = const InputDecoration(),
// 用于设置该输入框默认的键盘输入类型,取值如下:
// text:文本输入键盘; multiline:多行文本,需和maxLines配合使用(设为null或大于1);
// number:数字,会弹出数字键盘; phone:优化后的电话号码输入键盘,会弹出数字键盘并显示“* #”;
// datetime:优化后的日期输入键盘,Android上会显示“: -”; emailAddress:优化后的电子邮件地址,会显示“@ .”; url:优化后的url输入键盘,会显示“/ .”;
TextInputType keyboardType,
// 键盘动作按钮图标(即回车键位图标),它是一个枚举值,有多个可选值,全部的取值列表可查看官方API文档。
this.textInputAction,
this.textCapitalization = TextCapitalization.none,
// 正在编辑的文本样式。
this.style,
this.strutStyle,
// 输入框内编辑文本在水平方向的对齐方式。
this.textAlign = TextAlign.start,
this.textAlignVertical,
this.textDirection,
this.readOnly = false,
ToolbarOptions toolbarOptions,
this.showCursor,
// 是否自动获取焦点。
this.autofocus = false,
// 是否隐藏正在编辑的文本,如用于输入密码的场景等,文本内容会用“•”替换。
this.obscureText = false,
this.autocorrect = true,
// 输入框的最大行数,默认为1;如果为null,则无行数限制。
this.maxLines = 1,
this.minLines,
this.expands = false,
// maxLength代表输入框文本的最大长度,设置后输入框右下角会显示输入的文本计数。
this.maxLength,
// maxLengthEnforced决定当输入文本长度超过maxLength时是否阻止输入,为true时会阻止输入,为false时不会阻止输入但输入框会变红。
this.maxLengthEnforced = true,
// 输入框内容改变时的回调函数;注:内容改变事件也可以通过controller来监听。
this.onChanged,
// 这两个回调都是在输入框输入完成时触发,比如按了键盘的完成键(对号图标)或搜索键(图标)。
// 不同的是两个回调签名不同,onSubmitted回调是ValueChanged<String>类型,它接收当前输入内容做为参数,而onEditingComplete不接收参数。
this.onEditingComplete,
this.onSubmitted,
// 用于指定输入格式;当用户输入内容改变时,会根据指定的格式来校验。
this.inputFormatters,
// 如果为false,则输入框会被禁用,禁用状态不接收输入和事件,同时显示禁用态样式(在其decoration中定义)。
this.enabled,
// 这三个属性是用于自定义输入框光标的宽度、圆角和颜色。
this.cursorWidth = 2.0,
this.cursorRadius,
this.cursorColor,
this.keyboardAppearance,
this.scrollPadding = const EdgeInsets.all(20.0),
this.dragStartBehavior = DragStartBehavior.start,
this.enableInteractiveSelection = true,
this.onTap,
this.buildCounter,
this.scrollController,
this.scrollPhysics,
})

代码示例

class InputTest extends StatefulWidget {

  @override
_InputTestState createState() => _InputTestState();
} class _InputTestState extends State<InputTest> { // 获取输入内容
TextEditingController _uNameController = TextEditingController(); // 监听文本变化
TextEditingController _selectionController = TextEditingController(); @override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('输入框'),
),
body: Container(
child: Column(
children: <Widget>[
// 用户名输入框
TextField(
autofocus: true,
decoration: InputDecoration(
labelText: '用户名',
hintText: '用户名或邮箱',
prefixIcon: Icon(Icons.person),
),
controller: _uNameController,
), // 获取输入内容
Text('用户名:' + _uNameController.text), //密码输入框
TextField(
decoration: InputDecoration(
labelText: '密码',
hintText: '您的登录密码',
prefixIcon: Icon(Icons.lock),
),
obscureText: true,
// 监听文本变化
onChanged: (v) {
print('onChanged:$v');
},
), ],
),
),
);
}
}

代码解读

获取输入内容有两种方式:

  • 定义两个变量,用于保存用户名和密码,然后在onChange触发时,各自保存一下输入内容。
  • 通过controller直接获取。

监听文本变也有两种方式:

  • 设置onChange回调。
  • 通过controller监听。
  • 区别:onChanged是专门用于监听文本变化,而controller的功能却多一些,除了能监听文本变化外,它还可以设置默认值、选择文本。

代码示例

class FocusTestRoute extends StatefulWidget {
@override
_FocusTestRouteState createState() => _FocusTestRouteState();
} class _FocusTestRouteState extends State<FocusTestRoute> {
// 控制焦点-焦点控制范围
FocusNode focusNode1 = FocusNode();
FocusNode focusNode2 = FocusNode();
// 在输入框中移动焦点
FocusScopeNode focusScopeNode; @override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('控制焦点'),
),
body: Container(
child: Column(
children: <Widget>[
// 输入框1
TextField(
autofocus: true,
// 关联focusNode1
focusNode: focusNode1,
decoration: InputDecoration(
labelText: 'input1'
),
), // 输入框2
TextField(
// 关联focusNode2
focusNode: focusNode2,
decoration: InputDecoration(
labelText: 'input2'
),
), Builder(builder: (ctx) {
return Column(
children: <Widget>[
// 移动焦点按钮
RaisedButton(
child: Text('移动焦点'),
onPressed: () {
// 将焦点从第一个输入框移动到第二个
if(null == focusScopeNode){
focusScopeNode = FocusScope.of(context);
}
focusScopeNode.requestFocus(focusNode2);
// 第二种写法
// FocusScope.of(context).requestFocus(focusNode2);
},
), // 隐藏键盘按钮
RaisedButton(
child: Text('隐藏键盘'),
onPressed: () {
// 当所有编辑框都失去焦点时键盘就会收起
focusNode1.unfocus();
focusNode2.unfocus();
},
) ],
);
}) ],
),
),
);
} }

代码解读

焦点控制

  • 焦点可以通过FocusNode和FocusScopeNode来控制。
  • 默认情况下,焦点由FocusScope来管理,它代表焦点控制范围,可以在这个范围内可以通过FocusScopeNode在输入框之间移动焦点、设置默认焦点等。
  • 可以通过FocusScope.of(context) 来获取Widget树中默认的FocusScopeNode。

表单Form

接口描述

Form({
Key key,
@required this.child,
// 是否自动校验输入内容;当为true时,每一个子FormField内容发生变化时都会自动校验合法性,并直接显示错误信息。否则,需要通过调用FormState.validate()来手动校验。
this.autovalidate = false,
// 决定Form所在的路由是否可以直接返回(如点击返回按钮),该回调返回一个Future对象,如果Future的最终结果是false,则当前路由不会返回;如果为true,则会返回到上一个路由。此属性通常用于拦截返回按钮。
this.onWillPop,
// Form的任意一个子FormField内容发生变化时会触发此回调。
this.onChanged,
}) TextFormField({
Key key,
this.controller,
String initialValue,
FocusNode focusNode,
InputDecoration decoration = const InputDecoration(),
TextInputType keyboardType,
TextCapitalization textCapitalization = TextCapitalization.none,
TextInputAction textInputAction,
TextStyle style,
StrutStyle strutStyle,
TextDirection textDirection,
TextAlign textAlign = TextAlign.start,
bool autofocus = false,
bool readOnly = false,
ToolbarOptions toolbarOptions,
bool showCursor,
bool obscureText = false,
bool autocorrect = true,
bool autovalidate = false,
bool maxLengthEnforced = true,
int maxLines = 1,
int minLines,
bool expands = false,
int maxLength,
ValueChanged<String> onChanged,
GestureTapCallback onTap,
VoidCallback onEditingComplete,
ValueChanged<String> onFieldSubmitted,
FormFieldSetter<String> onSaved,
FormFieldValidator<String> validator,
List<TextInputFormatter> inputFormatters,
bool enabled = true,
double cursorWidth = 2.0,
Radius cursorRadius,
Color cursorColor,
Brightness keyboardAppearance,
EdgeInsets scrollPadding = const EdgeInsets.all(20.0),
bool enableInteractiveSelection = true,
InputCounterWidgetBuilder buildCounter,
})

代码示例

class FormTestRoute extends StatefulWidget {
@override
_FormTestRouteState createState() => _FormTestRouteState();
} class _FormTestRouteState extends State<FormTestRoute> {
//
TextEditingController _uNameController = TextEditingController();
//
TextEditingController _pwdController = TextEditingController();
//
GlobalKey _formKey = GlobalKey<FormState>(); @override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('表单'),
),
body: Padding(
padding: const EdgeInsets.symmetric(vertical: 16.0, horizontal: 24.0),
child: Form(
// 设置globalKey,用于后面获取FormState
key: _formKey,
// 是否自动校验输入内容;当为true时,每一个子FormField内容发生变化时都会自动校验合法性,并直接显示错误信息。
// 否则,需要通过调用FormState.validate()来手动校验。
autovalidate: true,
child: Column(
children: <Widget>[ // 用户名表单
TextFormField(
autofocus: true,
controller: _uNameController,
// 校验用户名
validator: (v) {
return v
.trim()
.length > 0 ? null : '用户名不能为空!';
},
decoration: InputDecoration(
labelText: '用户名',
hintText: '用户名或邮箱',
icon: Icon(Icons.person),
),
), // 密码表单
TextFormField(
controller: _pwdController,
obscureText: true,
// 校验密码
validator: (v) {
return v
.trim()
.length > 5 ? null : '密码不能少于6位!';
},
decoration: InputDecoration(
labelText: '密码',
hintText: '您的登录密码',
icon: Icon(Icons.lock),
),
), // 登录按钮
Padding(
padding: const EdgeInsets.only(top: 28.0),
child: Row(
children: <Widget>[
Expanded(
child: RaisedButton(
padding: EdgeInsets.all(15.0),
child: Text('登录'),
color: Theme.of(context).primaryColor,
textColor: Colors.white,
onPressed: () {
//验证通过提交数据
if((_formKey.currentState as FormState).validate()){
print('用户名:' + _uNameController.text);
print('密码:' + _pwdController.text);
}
else
print('输入不合法!');
},
), )
],
),
), ],
),
), ),
); }
}

代码解读

关于Form.of(context)

注意,登录按钮的onPressed方法中不能通过Form.of(context)来获取,原因是,此处的context为FormTestRoute的context,而Form.of(context)是根据所指定context向根去查找,而FormState是在FormTestRoute的子树中,所以不行。正确的做法是通过Builder来构建登录按钮,Builder会将widget节点的context作为回调参数。

Flutter 基础组件:输入框和表单的更多相关文章

  1. day75 form 组件(对form表单进行输入值校验的一种方式)

    我们的组件是什么呢 select distinct(id,title,price) from book ORM: model.py class Book(): title=model.CharFiel ...

  2. laravel基础课程---14、表单验证(lavarel如何进行表单验证)

    laravel基础课程---14.表单验证(lavarel如何进行表单验证) 一.总结 一句话总结: lavarel的验证的功能比tp要[简单]且[强大]很多 直接控制器中:添加[规则数组]和[修改提 ...

  3. Promise实现子组件的多表单校验并反馈结果给父组件

    全手打原创,转载请标明出处:https://www.cnblogs.com/dreamsqin/p/11529207.html,多谢,=.=~ 本文中多表单验证主要用到Promise.all()实现多 ...

  4. 【Flutter学习】基本组件之基本表单组件

    一,概述 表单时一个包含表单元素的区域. 表单元素允许用户输入内容,比如文本域,下拉列表,单选框,复选框等.常见的应用场景有:登录,注册,输入信息等. 表单里有两个重要的组件: Form:用来做整个表 ...

  5. Vue基础-自定义事件的表单输入组件、自定义组件的 v-model

    Vue 测试版本:Vue.js v2.5.13 学习 Vue 的自定义事件的表单输入组件,觉得文档讲的不太细致,所以这里再细化一下: 如果不用 v-model,代码应该是这样: <myinput ...

  6. Django组件之Form表单

    一.Django中的Form表单介绍 我们之前在HTML页面中利用form表单向后端提交数据时,都会写一些获取用户输入的标签并且用form标签把它们包起来. 与此同时我们在好多场景下都需要对用户的输入 ...

  7. 【HTML基础】表格和表单

    本次博客的主要内容如下: meta和link 表格 表单 meta和link meta meta的属性有两种:name和http-equiv. name属性主要用于描述网页内容,对应与网页内容. 1. ...

  8. angularcli 第五篇(输入框、表单处理)

    本文参考:Angular4 表单快速入门 注:涉及input表单时要在AppComponent中引入 FormsModule模块:     import{ FormsModule } from '@a ...

  9. JS组件系列——Form表单验证神器: BootstrapValidator

    前言:做Web开发的我们,表单验证是再常见不过的需求了.友好的错误提示能增加用户体验.博主搜索bootstrap表单验证,搜到的结果大部分都是文中的主题:bootstrapvalidator.今天就来 ...

随机推荐

  1. 【题解】「UVA10116」Robot Motion

    Simple Translation 让你模拟一个机器人行走的过程,如果机器人走入了一个循环,输出不是循环的长度和是循环的长度,如果最终走出来了,输出走的步数. Solution 直接模拟即可,本题难 ...

  2. 题解-Koishi Loves Construction

    题解-Koishi Loves Construction 前缀知识 质数 逆元 暴搜 Koishi Loves Construction 给定 \(X\),\(T\) 组测试数据,每次给一个 \(n\ ...

  3. 深度剖析目标检测算法YOLOV4

    深度剖析目标检测算法YOLOV4 目录 简述 yolo 的发展历程 介绍 yolov3 算法原理 介绍 yolov4 算法原理(相比于 yolov3,有哪些改进点) YOLOV4 源代码日志解读 yo ...

  4. docker下安装svn-server

    参考资料,搭建过程比较详细:https://www.jianshu.com/p/a25fac7e7811 我按照上面资料搭建后,将其重新制作成了新的镜像theorydance/svn-server:1 ...

  5. EHCACHE实现登录错误次数账号锁定

    使用EHCACHE实现账号密码登录校验失败5次锁定10分钟 <?xml version="1.0" encoding="UTF-8"?> <e ...

  6. 基础的DOS命令

    基础的dos命令 注:所有的命令以及符号应使用英文 打开CMD的方式 开始+系统+命令提示符 Win+R 输入cmd打开控制台 略 常用的dos命令 //切换盘符的方法:直接输入想进入的盘加冒号,例如 ...

  7. UML—20—003

    博客班级 https://edu.cnblogs.com/campus/fzzcxy/2018SE1 作业要求 https://edu.cnblogs.com/campus/fzzcxy/2018SE ...

  8. 开源一套原创文本处理工具:Java+Bat脚本实现自动批量处理对账单工具

    原创/朱季谦 这款工具是笔者在2018年初开发完成的,时隔两载,偶然想起这款小工具,于是,决定将其开源,若有人需要做类似Java批处理实现整理文档的工具,可参考该工具逻辑思路来实现. 该工具是运行在w ...

  9. remmina 软件rdp协议链接windows失败

    remmina 1.42  链接 win10 提示失败......其他版本win还没有测试过. 忘记了在那个论坛有是说加密问题,照着改确实可以.具体原因是默认设置加密方式这一项不知道为什么不起作用,手 ...

  10. 全能扫描王(一款识别率超高的OCR识别APP)

    前言 无论是在工作还是日常生活中,我们都会经常遇到,需要将一些纸质资料上的文字内容变成电子文档进行编辑.这个时候就需要拥有一款好用的手机扫描+OCR文字识别功能的应用了. 随着人工智能的兴起,我们都在 ...