1. 为什么你需要它?
在原生 Flutter 中开发表单,通常意味着"样板代码的灾难":
- 原生痛点 1: 每一个输入框都要创建一个
TextEditingController。 - 原生痛点 2: 页面销毁时,必须手动
dispose每一个 Controller,否则内存泄漏。 - 原生痛点 3: 获取数据困难,你需要自己把一个个 controller 的
.text拼装成 JSON 对象。 - 原生痛点 4: 像"单选框组"、"复选框组"、"日期选择"这种非文本组件,原生处理起来非常麻烦,往往需要自己写逻辑维护状态。
flutter_form_builder 的解决方案:
它采用 "数据驱动" 的思路。您不需要管理控制器,只需要给每个字段起个名字(name),就像 HTML 表单一样。提交时,它直接返还给您一个干净的 Map<String, dynamic>。
2. 快速开始
安装依赖
通常我们需要搭配它的验证库一起使用:
YAML
dependencies:
flutter:
sdk: flutter
# 核心库
flutter_form_builder: ^9.0.0
# 验证器库 (强烈推荐,提供了大量现成的正则校验)
form_builder_validators: ^10.0.0
Hello World 代码
看这一段代码,注意我们没有创建任何变量来存储输入内容:
Dart
import 'package:flutter/material.dart';
import 'package:flutter_form_builder/flutter_form_builder.dart';
import 'package:form_builder_validators/form_builder_validators.dart';
class SimpleLoginForm extends StatelessWidget {
// 1. 定义一个 GlobalKey,用来获取表单状态
final _formKey = GlobalKey<FormBuilderState>();
@override
Widget build(BuildContext context) {
return Scaffold(
body: Padding(
padding: const EdgeInsets.all(20.0),
// 2. 最外层包裹 FormBuilder
child: FormBuilder(
key: _formKey,
child: Column(
children: [
// 3. 字段 A:邮箱
FormBuilderTextField(
name: 'email', // 关键:这是存入 Map 的 key
decoration: InputDecoration(labelText: '邮箱'),
validator: FormBuilderValidators.compose([
FormBuilderValidators.required(),
FormBuilderValidators.email(),
]),
),
const SizedBox(height: 10),
// 4. 字段 B:密码
FormBuilderTextField(
name: 'password',
obscureText: true,
decoration: InputDecoration(labelText: '密码'),
validator: FormBuilderValidators.required(),
),
const SizedBox(height: 20),
// 5. 提交按钮
ElevatedButton(
onPressed: () {
// 保存并验证
if (_formKey.currentState?.saveAndValidate() ?? false) {
// ✅ 直接获取所有数据!
final formData = _formKey.currentState?.value;
print(formData);
// 输出: {email: "xx@xx.com", password: "123"}
}
},
child: Text('登录'),
)
],
),
),
),
);
}
}
3. 核心功能详解
A. 全家桶式的组件库
它不仅仅是封装了 TextField,它几乎封装了所有你能在表单里想到的组件。这意味着所有组件的 API 都是统一的。
| 组件名 | 对应原生/功能 | 用途示例 |
|---|---|---|
FormBuilderTextField |
TextField | 姓名、地址、备注 |
FormBuilderSwitch |
Switch | 开关 (GSP认证状态) |
FormBuilderCheckbox |
Checkbox | 单个勾选 (同意协议) |
FormBuilderCheckboxGroup |
原生没有 | 多选组 |
FormBuilderRadioGroup |
原生难用 | 单选组 (男/女) |
FormBuilderDateTimePicker |
DatePicker | 日期、有效期 |
FormBuilderDropdown |
DropdownButton | 下拉菜单 (选择省份) |
FormBuilderSlider |
Slider | 滑动条 (打分) |
B. 强大的校验 (Validators)
配合 form_builder_validators,你可以像搭积木一样组合校验规则,支持多语言错误提示。
Dart
FormBuilderTextField(
name: 'age',
validator: FormBuilderValidators.compose([
FormBuilderValidators.required(errorText: '年龄必填'),
FormBuilderValidators.numeric(errorText: '必须是数字'),
FormBuilderValidators.min(18, errorText: '必须满18岁'),
FormBuilderValidators.max(100),
]),
)
C. 数据回显 (Initial Value)
做"编辑页面"时,这一步通常很烦(要给 controller 赋值)。但在 FormBuilder 里,非常简单。
方法一:整体初始化 (推荐)
直接在最外层的 FormBuilder 传入一个 Map。
Dart
FormBuilder(
key: _formKey,
// 假设这是从后台 API 获取的详情数据
initialValue: {
'storeName': '同仁堂大药房',
'isGSP': true,
'score': 95,
},
child: ... // 下面的组件会自动匹配 key 并填入值
)
方法二:动态更新 (Patch)
如果数据是后来才请求回来的:
Dart
// 模拟 API 回调
void onLoadData(Map<String, dynamic> apiData) {
_formKey.currentState?.patchValue(apiData);
}
4. 动态表单的最佳实践
flutter_form_builder 是实现服务端驱动 UI 的核心。
场景: 后台下发 JSON,App 动态生成表单。
Dart
// 1. 定义渲染器
Widget buildField(Map<String, dynamic> fieldConfig) {
String type = fieldConfig['type'];
String key = fieldConfig['key']; // 比如 "store_name"
String label = fieldConfig['label'];
switch (type) {
case 'text':
return FormBuilderTextField(
name: key, // 直接用后台的 key 作为 name
decoration: InputDecoration(labelText: label),
);
case 'switch':
return FormBuilderSwitch(
name: key,
title: Text(label),
);
case 'date':
return FormBuilderDateTimePicker(
name: key,
inputType: InputType.date,
decoration: InputDecoration(labelText: label),
);
default:
return SizedBox.shrink();
}
}
// 2. 在页面中使用
// 无论后台发来什么结构,只要 key 对得上,
// _formKey.currentState.value 就能直接拿到最终的 JSON 数据。
5. 总结
相比于 Flutter 原生写法:
- 代码量减少: 至少减少 50% 以上的样板代码。
- 状态管理: 自动处理,无需手动
dispose。 - 数据流向: 提交时直接获得
Map/JSON,直接就能发给后端 API。 - 统一性: 无论是输入框、下拉框还是日期选择,用法完全一致。