【Flutter实战】Flutter表单处理与验证完整指南
### 文章目录
- [【Flutter实战】Flutter表单处理与验证完整指南](#文章目录 【Flutter实战】Flutter表单处理与验证完整指南 @[toc] 前言 一、表单基础组件 1.1 TextFormField基础 1.2 表单字段类型 二、表单验证封装 2.1 验证器封装 2.2 使用验证器 三、表单美化技巧 3.1 自定义边框 3.2 表单字段组件封装 四、复杂表单处理 4.1 多步骤表单 4.2 动态表单 总结)
- [@[toc]](#文章目录 【Flutter实战】Flutter表单处理与验证完整指南 @[toc] 前言 一、表单基础组件 1.1 TextFormField基础 1.2 表单字段类型 二、表单验证封装 2.1 验证器封装 2.2 使用验证器 三、表单美化技巧 3.1 自定义边框 3.2 表单字段组件封装 四、复杂表单处理 4.1 多步骤表单 4.2 动态表单 总结)
- [前言](#文章目录 【Flutter实战】Flutter表单处理与验证完整指南 @[toc] 前言 一、表单基础组件 1.1 TextFormField基础 1.2 表单字段类型 二、表单验证封装 2.1 验证器封装 2.2 使用验证器 三、表单美化技巧 3.1 自定义边框 3.2 表单字段组件封装 四、复杂表单处理 4.1 多步骤表单 4.2 动态表单 总结)
- [一、表单基础组件](#文章目录 【Flutter实战】Flutter表单处理与验证完整指南 @[toc] 前言 一、表单基础组件 1.1 TextFormField基础 1.2 表单字段类型 二、表单验证封装 2.1 验证器封装 2.2 使用验证器 三、表单美化技巧 3.1 自定义边框 3.2 表单字段组件封装 四、复杂表单处理 4.1 多步骤表单 4.2 动态表单 总结)
- [1.1 TextFormField基础](#文章目录 【Flutter实战】Flutter表单处理与验证完整指南 @[toc] 前言 一、表单基础组件 1.1 TextFormField基础 1.2 表单字段类型 二、表单验证封装 2.1 验证器封装 2.2 使用验证器 三、表单美化技巧 3.1 自定义边框 3.2 表单字段组件封装 四、复杂表单处理 4.1 多步骤表单 4.2 动态表单 总结)
- [1.2 表单字段类型](#文章目录 【Flutter实战】Flutter表单处理与验证完整指南 @[toc] 前言 一、表单基础组件 1.1 TextFormField基础 1.2 表单字段类型 二、表单验证封装 2.1 验证器封装 2.2 使用验证器 三、表单美化技巧 3.1 自定义边框 3.2 表单字段组件封装 四、复杂表单处理 4.1 多步骤表单 4.2 动态表单 总结)
- [二、表单验证封装](#文章目录 【Flutter实战】Flutter表单处理与验证完整指南 @[toc] 前言 一、表单基础组件 1.1 TextFormField基础 1.2 表单字段类型 二、表单验证封装 2.1 验证器封装 2.2 使用验证器 三、表单美化技巧 3.1 自定义边框 3.2 表单字段组件封装 四、复杂表单处理 4.1 多步骤表单 4.2 动态表单 总结)
- [2.1 验证器封装](#文章目录 【Flutter实战】Flutter表单处理与验证完整指南 @[toc] 前言 一、表单基础组件 1.1 TextFormField基础 1.2 表单字段类型 二、表单验证封装 2.1 验证器封装 2.2 使用验证器 三、表单美化技巧 3.1 自定义边框 3.2 表单字段组件封装 四、复杂表单处理 4.1 多步骤表单 4.2 动态表单 总结)
- [2.2 使用验证器](#文章目录 【Flutter实战】Flutter表单处理与验证完整指南 @[toc] 前言 一、表单基础组件 1.1 TextFormField基础 1.2 表单字段类型 二、表单验证封装 2.1 验证器封装 2.2 使用验证器 三、表单美化技巧 3.1 自定义边框 3.2 表单字段组件封装 四、复杂表单处理 4.1 多步骤表单 4.2 动态表单 总结)
- [三、表单美化技巧](#文章目录 【Flutter实战】Flutter表单处理与验证完整指南 @[toc] 前言 一、表单基础组件 1.1 TextFormField基础 1.2 表单字段类型 二、表单验证封装 2.1 验证器封装 2.2 使用验证器 三、表单美化技巧 3.1 自定义边框 3.2 表单字段组件封装 四、复杂表单处理 4.1 多步骤表单 4.2 动态表单 总结)
- [3.1 自定义边框](#文章目录 【Flutter实战】Flutter表单处理与验证完整指南 @[toc] 前言 一、表单基础组件 1.1 TextFormField基础 1.2 表单字段类型 二、表单验证封装 2.1 验证器封装 2.2 使用验证器 三、表单美化技巧 3.1 自定义边框 3.2 表单字段组件封装 四、复杂表单处理 4.1 多步骤表单 4.2 动态表单 总结)
- [3.2 表单字段组件封装](#文章目录 【Flutter实战】Flutter表单处理与验证完整指南 @[toc] 前言 一、表单基础组件 1.1 TextFormField基础 1.2 表单字段类型 二、表单验证封装 2.1 验证器封装 2.2 使用验证器 三、表单美化技巧 3.1 自定义边框 3.2 表单字段组件封装 四、复杂表单处理 4.1 多步骤表单 4.2 动态表单 总结)
- [四、复杂表单处理](#文章目录 【Flutter实战】Flutter表单处理与验证完整指南 @[toc] 前言 一、表单基础组件 1.1 TextFormField基础 1.2 表单字段类型 二、表单验证封装 2.1 验证器封装 2.2 使用验证器 三、表单美化技巧 3.1 自定义边框 3.2 表单字段组件封装 四、复杂表单处理 4.1 多步骤表单 4.2 动态表单 总结)
- [4.1 多步骤表单](#文章目录 【Flutter实战】Flutter表单处理与验证完整指南 @[toc] 前言 一、表单基础组件 1.1 TextFormField基础 1.2 表单字段类型 二、表单验证封装 2.1 验证器封装 2.2 使用验证器 三、表单美化技巧 3.1 自定义边框 3.2 表单字段组件封装 四、复杂表单处理 4.1 多步骤表单 4.2 动态表单 总结)
- [4.2 动态表单](#文章目录 【Flutter实战】Flutter表单处理与验证完整指南 @[toc] 前言 一、表单基础组件 1.1 TextFormField基础 1.2 表单字段类型 二、表单验证封装 2.1 验证器封装 2.2 使用验证器 三、表单美化技巧 3.1 自定义边框 3.2 表单字段组件封装 四、复杂表单处理 4.1 多步骤表单 4.2 动态表单 总结)
- [总结](#文章目录 【Flutter实战】Flutter表单处理与验证完整指南 @[toc] 前言 一、表单基础组件 1.1 TextFormField基础 1.2 表单字段类型 二、表单验证封装 2.1 验证器封装 2.2 使用验证器 三、表单美化技巧 3.1 自定义边框 3.2 表单字段组件封装 四、复杂表单处理 4.1 多步骤表单 4.2 动态表单 总结)
前言
表单处理看似简单,实则有很多细节。验证规则、错误提示、提交逻辑,每一项都需要仔细考虑。
我做过的表单从简单的登录注册,到复杂的多步骤向导,积累了不少经验。这篇文章我想分享表单处理的实践技巧。
一、表单基础组件

1.1 TextFormField基础
dart
class BasicForm extends StatefulWidget {
@override
State<BasicForm> createState() => _BasicFormState();
}
class _BasicFormState extends State<BasicForm> {
final _formKey = GlobalKey<FormState>();
final _nameController = TextEditingController();
final _emailController = TextEditingController();
@override
void dispose() {
_nameController.dispose();
_emailController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Form(
key: _formKey,
child: Column(
children: [
TextFormField(
controller: _nameController,
decoration: InputDecoration(
labelText: '姓名',
prefixIcon: Icon(Icons.person),
border: OutlineInputBorder(),
),
validator: (value) {
if (value == null || value.isEmpty) {
return '请输入姓名';
}
return null;
},
),
SizedBox(height: 16),
TextFormField(
controller: _emailController,
decoration: InputDecoration(
labelText: '邮箱',
prefixIcon: Icon(Icons.email),
border: OutlineInputBorder(),
),
keyboardType: TextInputType.emailAddress,
validator: (value) {
if (value == null || value.isEmpty) {
return '请输入邮箱';
}
if (!value.contains('@')) {
return '请输入有效的邮箱地址';
}
return null;
},
),
SizedBox(height: 24),
ElevatedButton(
onPressed: _submitForm,
child: Text('提交'),
),
],
),
);
}
void _submitForm() {
if (_formKey.currentState!.validate()) {
print('姓名: ${_nameController.text}');
print('邮箱: ${_emailController.text}');
}
}
}
1.2 表单字段类型
dart
// 密码输入
TextFormField(
obscureText: true,
decoration: InputDecoration(
labelText: '密码',
suffixIcon: Icon(Icons.visibility),
),
)
// 多行输入
TextFormField(
maxLines: 5,
decoration: InputDecoration(
labelText: '描述',
),
)
// 数字输入
TextFormField(
keyboardType: TextInputType.number,
decoration: InputDecoration(labelText: '年龄'),
)
二、表单验证封装
2.1 验证器封装
dart
class Validators {
static final RegExp _emailRegExp = RegExp(
r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$',
);
static final RegExp _phoneRegExp = RegExp(
r'^1[3-9]\d{9}$',
);
static String? required(String? value, [String message = '此项不能为空']) {
if (value == null || value.isEmpty) {
return message;
}
return null;
}
static String? email(String? value) {
if (value == null || value.isEmpty) {
return '请输入邮箱';
}
if (!_emailRegExp.hasMatch(value)) {
return '请输入有效的邮箱地址';
}
return null;
}
static String? phone(String? value) {
if (value == null || value.isEmpty) {
return '请输入手机号';
}
if (!_phoneRegExp.hasMatch(value)) {
return '请输入有效的手机号';
}
return null;
}
static String? length(String? value, int min, int max) {
if (value == null || value.isEmpty) {
return '请输入内容';
}
if (value.length < min || value.length > max) {
return '长度应在$min到$max之间';
}
return null;
}
}
2.2 使用验证器
dart
TextFormField(
decoration: InputDecoration(labelText: '邮箱'),
validator: Validators.email,
)
三、表单美化技巧
3.1 自定义边框
dart
TextFormField(
decoration: InputDecoration(
labelText: '用户名',
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
borderSide: BorderSide(color: Colors.blue, width: 2),
),
errorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
borderSide: BorderSide(color: Colors.red),
),
),
)
3.2 表单字段组件封装
dart
class AppTextField extends StatelessWidget {
final String label;
final IconData? icon;
final bool obscureText;
final String? Function(String?)? validator;
final TextEditingController? controller;
const AppTextField({
super.key,
required this.label,
this.icon,
this.obscureText = false,
this.validator,
this.controller,
});
@override
Widget build(BuildContext context) {
return TextFormField(
controller: controller,
obscureText: obscureText,
validator: validator,
decoration: InputDecoration(
labelText: label,
prefixIcon: icon != null ? Icon(icon) : null,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
),
),
);
}
}
四、复杂表单处理

4.1 多步骤表单
dart
class MultiStepForm extends StatefulWidget {
@override
State<MultiStepForm> createState() => _MultiStepFormState();
}
class _MultiStepFormState extends State<MultiStepForm> {
int _currentStep = 0;
final _formKeys = [
GlobalKey<FormState>(),
GlobalKey<FormState>(),
GlobalKey<FormState>(),
];
List<Step> get _steps => [
Step(
title: Text('基本信息'),
content: Form(
key: _formKeys[0],
child: Column(
children: [
AppTextField(label: '姓名', validator: Validators.required),
SizedBox(height: 16),
AppTextField(label: '邮箱', validator: Validators.email),
],
),
),
isActive: _currentStep >= 0,
),
Step(
title: Text('详细信息'),
content: Form(
key: _formKeys[1],
child: Column(
children: [
AppTextField(label: '电话', validator: Validators.phone),
],
),
),
isActive: _currentStep >= 1,
),
Step(
title: Text('确认'),
content: Form(
key: _formKeys[2],
child: Column(
children: [
Text('请确认信息'),
],
),
),
isActive: _currentStep >= 2,
),
];
@override
Widget build(BuildContext context) {
return Stepper(
currentStep: _currentStep,
steps: _steps,
onStepContinue: () {
if (_currentStep < _steps.length - 1) {
if (_formKeys[_currentStep].currentState!.validate()) {
setState(() => _currentStep++);
}
}
},
onStepCancel: () {
if (_currentStep > 0) {
setState(() => _currentStep--);
}
},
);
}
}
4.2 动态表单
dart
class DynamicForm extends StatefulWidget {
@override
State<DynamicForm> createState() => _DynamicFormState();
}
class _DynamicFormState extends State<DynamicForm> {
final List<TextEditingController> _controllers = [];
void _addItem() {
setState(() {
_controllers.add(TextEditingController());
});
}
void _removeItem(int index) {
setState(() {
_controllers[index].dispose();
_controllers.removeAt(index);
});
}
@override
void dispose() {
for (var controller in _controllers) {
controller.dispose();
}
super.dispose();
}
@override
Widget build(BuildContext context) {
return Column(
children: [
..._controllers.asMap().entries.map((entry) {
final index = entry.key;
final controller = entry.value;
return Padding(
padding: const EdgeInsets.only(bottom: 16),
child: Row(
children: [
Expanded(
child: TextFormField(
controller: controller,
decoration: InputDecoration(labelText: '项目 ${index + 1}'),
),
),
IconButton(
icon: Icon(Icons.delete),
onPressed: () => _removeItem(index),
),
],
),
);
}),
ElevatedButton.icon(
onPressed: _addItem,
icon: Icon(Icons.add),
label: Text('添加项目'),
),
],
);
}
}
总结
表单处理需要注意细节。
核心要点:
- 使用Form和GlobalKey管理表单
- 封装验证器提高复用性
- 提供清晰的错误提示
- 美化表单提升体验
- 处理好提交状态
最佳实践:
- 实时验证反馈
- 防重复提交
- 保存草稿功能
- 自动填充支持
- 无障碍支持
好的表单设计让用户输入更顺畅。
欢迎加入开源鸿蒙跨平台社区:开源鸿蒙跨平台开发者社区