目录
1. 引言
在 Flutter 中,TextFormField
是 TextField
的扩展版本,专为表单输入设计。它除了继承 TextField
的所有功能外,还提供了输入验证、表单状态管理等功能,使其成为表单输入的最佳选择。本文将介绍 TextFormField
的基本用法、主要属性及自定义样式。
2. TextFormField 的基本用法
TextFormField
需要与 Form
组件一起使用,并通过 GlobalKey<FormState>
进行表单状态管理。
final _formKey = GlobalKey<FormState>();
Form(
key: _formKey,
child: Column(
children: [
TextFormField(
decoration: InputDecoration(labelText: '用户名'),
validator: (value) {
if (value == null || value.isEmpty) {
return '请输入用户名';
}
return null;
},
),
ElevatedButton(
onPressed: () {
if (_formKey.currentState!.validate()) {
print('表单验证通过');
}
},
child: Text('提交'),
),
],
),
)
3. 主要属性
属性 | 说明 |
---|---|
controller |
获取和控制输入框的内容 |
decoration |
自定义输入框外观,如边框、标签等 |
keyboardType |
设置键盘类型(文本、数字、邮箱等) |
obscureText |
是否隐藏输入内容(密码输入) |
validator |
用于验证输入内容是否合法 |
onSaved |
表单提交时保存输入值 |
示例:
TextFormField(
decoration: InputDecoration(hintText: '请输入密码'),
obscureText: true,
validator: (value) {
if (value == null || value.length < 6) {
return '密码长度至少为6位';
}
return null;
},
)
4. 自定义 TextFormField 样式
4.1 设置边框样式
TextFormField(
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: '邮箱',
),
)
4.2 设置输入格式限制
TextFormField(
keyboardType: TextInputType.number,
inputFormatters: [FilteringTextInputFormatter.digitsOnly],
)
4.3 多行输入
TextFormField(
maxLines: 5,
decoration: InputDecoration(labelText: '留言'),
)
5. 结论
TextFormField
是 Flutter 中用于表单输入的增强版 TextField
,支持输入验证、状态管理等功能,适用于用户注册、登录等场景。结合 Form
组件,可实现完整的表单交互,提高应用的可用性。一个完整的注册页面代码如下:
import 'package:flutter/material.dart';
class ScRegisterPage extends StatefulWidget {
@override
_ScRegisterPageState createState() => _ScRegisterPageState();
}
class _ScRegisterPageState extends State<ScRegisterPage> {
final _formKey = GlobalKey<FormState>();
final _scaffoldKey = GlobalKey<ScaffoldState>();
FocusNode _userNameNode = new FocusNode();
FocusNode _pwdNode = new FocusNode();
FocusNode _pwd2Node = new FocusNode();
late String _username,_pwd,_pwd2;
@override
Widget build(BuildContext context) {
return Scaffold(
key: _scaffoldKey,
appBar: AppBar(
title: Text("注册"),
),
//Form
body: Form(
key: _formKey,
child: ListView(
// 输入框会弹出软键盘,所以加个滑动的View
padding: EdgeInsets.fromLTRB(22.0, 18.0, 22.0, 0.0),
children: <Widget>[
_buildUserName(),
_buildPwd(),
_buildPwd2(),
_buildRegister(),
],
)),
);
}
Widget _buildUserName() {
return TextFormField(
focusNode: _userNameNode,
//以用户名输入框 为默认焦点,则进入页面会自动弹出软键盘
autofocus: true,
decoration: InputDecoration(
labelText: "用户名",
),
// 如键盘动作类型
textInputAction: TextInputAction.next,
onEditingComplete: () {
//按下action 的响应
FocusScope.of(context).requestFocus(_pwdNode);
},
//校验
validator: (value) {
if (value!.trim().isEmpty) {
//错误提示
return "请输入用户名";
}
_username = value;
},
);
}
Widget _buildPwd() {
return TextFormField(
focusNode: _pwdNode,
//以用户名输入框 为默认焦点,则进入页面会自动弹出软键盘
autofocus: true,
decoration: InputDecoration(
labelText: "密码",
),
// 如键盘动作类型
textInputAction: TextInputAction.next,
onEditingComplete: () {
//按下action 的响应
FocusScope.of(context).requestFocus(_pwd2Node);
},
//校验
validator: (value) {
if (value!.trim().isEmpty) {
//错误提示
return "请输入密码";
}
_pwd = value;
},
);
}
Widget _buildPwd2() {
return TextFormField(
focusNode: _pwd2Node,
//以用户名输入框 为默认焦点,则进入页面会自动弹出软键盘
autofocus: true,
decoration: InputDecoration(
labelText: "确认密码",
),
// 如键盘动作类型
textInputAction: TextInputAction.go,
onEditingComplete: () {
//按下action 的响应
_click();
},
//校验
validator: (value) {
if (value!.trim().isEmpty) {
//错误提示
return "请确认密码";
}
if(_pwd != value){
return "两次密码输入不一致";
}
_pwd2 = value;
},
);
}
Widget _buildRegister() {
///Container:装饰性容器
return Container(
height: 52.0,
margin: EdgeInsets.only(top: 18.0),
child: ElevatedButton(
style: ElevatedButton.styleFrom(
foregroundColor: Colors.white, // 文字颜色
backgroundColor:Theme.of(context).primaryColor, // 背景色
),
onPressed: _click,
child: Text(
"注册",
style: TextStyle(color: Colors.white, fontSize: 18.0),
),
),
);
}
_click() async{
//点击注册按钮 让软键盘隐藏
_userNameNode.unfocus();
_pwdNode.unfocus();
_pwd2Node.unfocus();
//校验输入内容
if (_formKey.currentState!.validate()) {
//弹出一个加载框
// barrierDismissible: 不允许按返回dismiss
showDialog(context: context,barrierDismissible: false,builder: (_){
return Center(child: CircularProgressIndicator(),);
});
//可以调用后端接口去注册了
// var result = await SccApi.register(_username,_pwd);
// //对话框dismiss
// Navigator.pop(context);
// if(result['errorCode'] == -1){
// var error = result['errorMsg'];
// //弹出提示
// // Toast.show(error, context,gravity: Toast.CENTER);
// }else{
// //Toast.show("注册成功!", context,gravity: Toast.CENTER);
// Navigator.pop(context);
// }
}
}
}