Form 表单在开发中必不可少,在 Flutter 中画一个像模像样的 Form 表单,对于一个初学者也不是件容易的事情,这里面不仅涉及到各种基础控件的使用,还涉及到样式的调整。现在就拿一个登录表单来练练手。
功能说明:
- 用户名必填,提交时做必输、长度验证;
- 密码必填,提交表单时做必输验证;
- 用户名、密码输入有标签、图标,还有对应的提示文字
- 点击重置按钮,可清空表单;
- 点击登录按钮,在控制台打印 用户名和密码。
用户体验提升: - 首次进入页面,焦点落在 用户名 输入框上;
- 用户名输入完成后,点击回车键,换行到密码输入文本框;
- 密码输入后,使用***输入,保证用户数据安全;
- 重置、登录按钮在一行展示。
登录页面样式构建;
import 'package:flutter/material.dart';
// 登录页面
class LoginRoute extends StatefulWidget{
@override
State<StatefulWidget> createState() {
return _LoginRouteState();
}
}
class _LoginRouteState extends State<LoginRoute>{
// 名称的控制器,通过它可以设置/获取编辑框的内容、选择编辑内容
TextEditingController _usernameController = new TextEditingController();
// 密码的控制器
TextEditingController _pwdController = new TextEditingController();
// 密码框 焦点节点 绑定,是否占有当前键盘的输入焦点
FocusNode passwordFocusNode = FocusNode();
// 一个GlobalKey代表一个表单对象
GlobalKey<FormState> formGloalKey = GlobalKey<FormState>();
// 用户名
var username;
// 密码
var password;
// 按钮样式的设定
final ButtonStyle style = ElevatedButton.styleFrom(textStyle: const TextStyle(fontSize: 15));
// 初始化事件
@override
void initState() {
super.initState();
}
// 保存事件
void save(){
var form = formGloalKey.currentState;
if(form!.validate()){
debugPrint("验证全部通过,用户名为:${_usernameController.text}, 密码为:${_pwdController.text}");
form.save();
}
}
// 重置事件
void reset(){
var form = formGloalKey.currentState;
debugPrint("表单重置了");
form!.reset();
}
//登录页面组件绘制
@override
Widget build(BuildContext context) {
return Container(
// 上下左右各填充16像素补白
padding: EdgeInsets.all(16.0),
child: Form(
key: formGloalKey,
child: Column(
//显式指定对齐方式为左对齐,排除对齐干扰
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
TextFormField(
// 回车键位图标,回车键变成下一页
textInputAction: TextInputAction.next,
// 当名称输完时,点击下一项,定位到密码输入框
onEditingComplete: ()=>FocusScope.of(context).requestFocus(passwordFocusNode),
// 输入框内容改变事件
onChanged: (context){
debugPrint(context);
},
// 打开该页面时,焦点落脚处
autofocus: true,
// 控制器
controller: _usernameController,
/// 用于设置该输入框默认的键盘输入类型,优化后的电子邮件地址;会显示@符号:
/// text、multiline、number、phone、datetime、emailAddress、url
keyboardType: TextInputType.emailAddress,
decoration: InputDecoration(
// 标签图标
prefixIcon: Icon(Icons.person),
// 标签文字
labelText: '登录名',
// 提示文字
hintText: '手机号或邮箱'
),
validator: (context){
if(context!.length <= 0){
return '姓名太短';
}
if(context.length > 8){
return '姓名太长';
}
},
onSaved: (context){
username = context;
},
),
TextFormField(
// 回车键变成完成
textInputAction: TextInputAction.done,
// 设置node指向
focusNode: passwordFocusNode,
// 最大长度限制
maxLength: 8,
// 控制器指向
controller: _pwdController,
// 输入的密码以圆点展示
obscureText: true,
decoration: InputDecoration(
// 标签图标
prefixIcon: Icon(Icons.lock),
// 标签上的文本
labelText: '密码',
hintText: '请输入你的密码',
),
validator: (context){
if(context!.isEmpty){
return '密码不能为空';
}
},
onSaved: (context){
password = context;
},
),
// 把重置按钮和登录按钮放在一行
Row(
children: [
// 重置按钮
Padding(
// 用于设置对称方向的填充,vertical指top和bottom,horizontal指left和right
padding: EdgeInsets.symmetric(horizontal: 50),
child: OutlinedButton(
child: Text('重置'),
onPressed: () {
reset();
},
),
),
// 登录按钮
Padding(
// 用于设置对称方向的填充,vertical指top和bottom,horizontal指left和right
padding: EdgeInsets.symmetric(horizontal: 50),
child : ElevatedButton(
style: style,
child: Text('登录'),
// 按钮点击事件
onPressed: () {
save();
},
),
),
],
),
],
),
),
);
}
}
说明:
- TextEditingController 为文本输入框的控制器,每个文本框对应一个输入框,如果多个文本框使用一个,那么这几个输入框的内容就会同步,也就相当于一个控件;
- TextFormField 是和 Form 表单搭配使用的;单独的文本框,使用 TextField 控件即可;
- 两个按钮展示在一行,这里用到了 Row 组件;
- 控件间距离的设定,用到了 Padding 组件;
- 按钮控件,这里使用了两种类型的按钮:ElevatedButton、OutlinedButton,还有一种类型的按钮 TextButton,其中 ElevatedButton 是默认风格的按钮,也是最长使用的按钮。
最后把 LoginRoute 加入到 main 方法里,运行一下,看看运行结果;
登录页面初始化
说明:焦点落在了第一个文本框,回车键变成了下一项;
验证提示说明:没有输入任何文字,点击登录,表单验证不通过;
验证通过时,控制台正确打印用户名密码信息 点击重置按钮,文本框内被清空
网友评论