TextField
TextField 是 Material 文本输入框,TextFormField 是带表单验证的输入框。
构造函数
TextField
dart
TextField({
Key? key, // 组件标识
TextEditingController? controller, // 控制器(获取/设置文本内容)
FocusNode? focusNode, // 焦点控制
InputDecoration? decoration = const InputDecoration(), // 装饰(标签、提示、图标等)
TextInputType? keyboardType, // 键盘类型
TextInputAction? textInputAction, // 键盘操作按钮(下一步/完成等)
TextCapitalization textCapitalization = TextCapitalization.none, // 自动大写
TextStyle? style, // 文字样式
StrutStyle? strutStyle, // 行间距样式
TextAlign textAlign = TextAlign.start, // 文字对齐
TextAlignVertical? textAlignVertical, // 文字垂直对齐
TextDirection? textDirection, // 文字方向
bool readOnly = false, // 是否只读
ToolbarOptions? toolbarOptions, // 工具栏选项(复制/粘贴等)
bool? showCursor, // 是否显示光标
bool autofocus = false, // 是否自动获取焦点
String obscuringCharacter = '•', // 密码遮罩字符
bool obscureText = false, // 是否隐藏文本(密码模式)
bool autocorrect = true, // 是否自动纠错
SmartDashesType? smartDashesType, // 智能破折号
SmartQuotesType? smartQuotesType, // 智能引号
bool enableSuggestions = true, // 是否启用建议
int? maxLength, // 最大字符数
int? maxLines = 1, // 最大行数(null 为无限行)
int? minLines, // 最小行数
bool expands = false, // 是否撑满父容器高度
double? maxLengthEnforcement, // 最大长度限制方式
ValueChanged<String>? onChanged, // 文字变化回调
VoidCallback? onEditingComplete, // 编辑完成回调(按下键盘完成按钮)
ValueChanged<String>? onSubmitted, // 提交回调(按下键盘完成按钮,带值)
AppPrivateCommandCallback? onAppPrivateCommand, // 私有命令回调
List<TextInputFormatter>? inputFormatters, // 输入格式化器
bool? enabled, // 是否启用
double cursorWidth = 2.0, // 光标宽度
double? cursorHeight, // 光标高度
Radius? cursorRadius, // 光标圆角
Color? cursorColor, // 光标颜色
BoxHeightStyle selectionHeightStyle = BoxHeightStyle.tight, // 选中区域高度样式
BoxWidthStyle selectionWidthStyle = BoxWidthStyle.tight, // 选中区域宽度样式
Brightness? keyboardAppearance, // 键盘外观(亮/暗)
EdgeInsets scrollPadding = const EdgeInsets.all(20), // 滚动内边距
DragStartBehavior dragStartBehavior = DragStartBehavior.start, // 拖拽行为
bool? enableInteractiveSelection, // 是否允许选择文本
TextSelectionControls? selectionControls, // 选择控制
GestureTapCallback? onTap, // 点击回调
MouseCursor? mouseCursor, // 鼠标指针
InputCounterWidgetBuilder? buildCounter, // 自定义计数器
ScrollController? scrollController, // 滚动控制器
ScrollPhysics? scrollPhysics, // 滚动物理效果
Iterable<String>? autofillHints, // 自动填充提示
String? restorationId, // 状态恢复 ID
})TextFormField
dart
TextFormField({ // 带表单验证的输入框
Key? key,
String? initialValue, // 初始值(不能与 controller 同时使用)
TextEditingController? controller,
String? validator, // 验证函数(返回 null 为通过)
AutovalidateMode? autovalidateMode, // 自动验证模式
FormFieldSetter<String>? onSaved, // 表单保存回调
...其余参数与 TextField 相同...
})InputDecoration
dart
InputDecoration({
Widget? icon, // 输入框左侧外部图标
Color? iconColor, // 图标颜色
Widget? label, // 标签组件(浮动效果)
String? labelText, // 标签文字
TextStyle? labelStyle, // 标签样式
Color? floatingLabelStyle, // 浮动标签样式
Widget? helper, // 帮助组件
String? helperText, // 帮助文字
int? helperMaxLines, // 帮助最大行数
TextStyle? helperStyle, // 帮助样式
int? counterText, // 计数器文字
Widget? counter, // 计数器组件
int? counterText, // 计数器文字
TextStyle? counterStyle, // 计数器样式
bool filled = false, // 是否填充背景
Color? fillColor, // 填充颜色
Color? focusColor, // 焦点颜色
Color? hoverColor, // 悬停颜色
Widget? prefix, // 前缀组件(内部左侧)
String? prefixText, // 前缀文字
TextStyle? prefixStyle, // 前缀样式
Color? prefixIconColor, // 前缀图标颜色
Widget? prefixIcon, // 前缀图标(内部左侧)
Widget? suffix, // 后缀组件(内部右侧)
String? suffixText, // 后缀文字
TextStyle? suffixStyle, // 后缀样式
Color? suffixIconColor, // 后缀图标颜色
Widget? suffixIcon, // 后缀图标(内部右侧)
Widget? prefixIcon, // 前缀图标
String? hintText, // 提示文字(输入前显示)
TextStyle? hintStyle, // 提示样式
String? errorText, // 错误文字(不为 null 时显示错误状态)
TextStyle? errorStyle, // 错误样式
int? errorMaxLines, // 错误最大行数
bool isDense = false, // 是否紧凑布局
bool isCollapsed = false, // 是否折叠(无内边距)
FloatingLabelBehavior? floatingLabelBehavior, // 浮动标签行为
EdgeInsetsGeometry? contentPadding, // 内容内边距
InputBorder? border, // 边框
InputBorder? enabledBorder, // 启用状态边框
InputBorder? focusedBorder, // 焦点状态边框
InputBorder? errorBorder, // 错误状态边框
InputBorder? focusedErrorBorder, // 焦点错误状态边框
InputBorder? disabledBorder, // 禁用状态边框
})属性速查
TextField 核心属性
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
controller | TextEditingController? | null | 控制器,用于获取/设置文本 |
decoration | InputDecoration | 默认 | 输入框装饰 |
keyboardType | TextInputType? | text | 键盘类型 |
obscureText | bool | false | 是否密码模式 |
maxLines | int? | 1 | 最大行数,null 为无限行 |
maxLength | int? | null | 最大字符数 |
onChanged | ValueChanged<String>? | null | 文字变化回调 |
onSubmitted | ValueChanged<String>? | null | 提交回调 |
enabled | bool? | true | 是否启用 |
readOnly | bool | false | 是否只读 |
autofocus | bool | false | 是否自动焦点 |
InputDecoration 核心属性
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
labelText | String? | null | 标签文字(浮动效果) |
hintText | String? | null | 提示文字(输入前灰色文字) |
prefixIcon | Widget? | null | 内部左侧图标 |
suffixIcon | Widget? | null | 内部右侧图标 |
prefixText | String? | null | 内部左侧文字 |
suffixText | String? | null | 内部右侧文字 |
helperText | String? | null | 帮助文字(输入框下方) |
errorText | String? | null | 错误文字(不为 null 时显示错误) |
filled | bool | false | 是否填充背景色 |
fillColor | Color? | null | 填充颜色 |
isDense | bool | false | 紧凑布局 |
contentPadding | EdgeInsetsGeometry? | null | 内容内边距 |
border | InputBorder? | null | 边框 |
counterText | String? | null | 自定义计数器文字 |
keyboardType 速查
| 值 | 键盘类型 | 用途 |
|---|---|---|
TextInputType.text | 标准键盘 | 通用文本 |
TextInputType.number | 数字键盘 | 数字输入 |
TextInputType.phone | 电话键盘 | 电话号码 |
TextInputType.emailAddress | 带 @ 的键盘 | 邮箱 |
TextInputType.url | 带 / 的键盘 | 网址 |
TextInputType.multiline | 多行键盘 | 多行文本 |
TextInputType.visiblePassword | 密码键盘 | 密码 |
TextInputType.name | 人名键盘 | 姓名 |
textInputAction 速查
| 值 | 键盘按钮 | 用途 |
|---|---|---|
TextInputAction.done | 完成 | 最后一个输入框 |
TextInputAction.go | 前往 | URL 输入 |
TextInputAction.search | 搜索 | 搜索框 |
TextInputAction.next | 下一项 | 表单下一字段 |
TextInputAction.previous | 上一项 | 表单上一字段 |
TextInputAction.newline | 换行 | 多行文本 |
InputBorder 速查
| 边框类型 | 说明 |
|---|---|
UnderlineInputBorder() | 底部横线(默认) |
UnderlineInputBorder(borderRadius: BorderRadius.circular(8)) | 圆角底线 |
OutlineInputBorder() | 全边框 |
OutlineInputBorder(borderRadius: BorderRadius.circular(8)) | 圆角全边框 |
InputBorder.none | 无边框 |
快速示例
基本输入框
dart
TextField(
decoration: InputDecoration(
labelText: '用户名',
hintText: '请输入用户名',
prefixIcon: Icon(Icons.person),
),
)密码输入框
dart
TextField(
obscureText: true,
decoration: InputDecoration(
labelText: '密码',
prefixIcon: Icon(Icons.lock),
suffixIcon: Icon(Icons.visibility_off), // 密码可见切换
),
)多行输入框
dart
TextField(
maxLines: 5, // 固定 5 行
// maxLines: null, // 无限行,自适应
decoration: InputDecoration(
labelText: '备注',
alignLabelWithHint: true, // 标签对齐到顶部
),
)带控制器的输入框
dart
final controller = TextEditingController(text: '初始值');
TextField(
controller: controller,
decoration: InputDecoration(labelText: '标题'),
);
// 获取文本
String text = controller.text;
// 监听变化
controller.addListener(() {
print(controller.text);
});
// 设置文本
controller.text = '新值';
// 清空
controller.clear();带验证的表单输入框
dart
Form(
key: formKey,
child: Column(
children: [
TextFormField(
decoration: InputDecoration(labelText: '邮箱'),
validator: (value) {
if (value == null || value.isEmpty) return '请输入邮箱';
if (!value.contains('@')) return '邮箱格式不正确';
return null; // null 表示验证通过
},
),
TextFormField(
decoration: InputDecoration(labelText: '密码'),
obscureText: true,
validator: (value) {
if (value == null || value.length < 6) return '密码至少6位';
return null;
},
),
ElevatedButton(
onPressed: () {
if (formKey.currentState!.validate()) {
// 验证通过
}
},
child: Text('提交'),
),
],
),
)自定义样式的输入框
dart
TextField(
decoration: InputDecoration(
labelText: '搜索',
prefixIcon: Icon(Icons.search),
filled: true, // 填充背景
fillColor: Colors.grey[200], // 背景色
isDense: true, // 紧凑
contentPadding: EdgeInsets.symmetric(horizontal: 16, vertical: 12),
border: OutlineInputBorder( // 默认边框
borderRadius: BorderRadius.circular(24),
borderSide: BorderSide.none, // 无边框线
),
enabledBorder: OutlineInputBorder( // 启用状态
borderRadius: BorderRadius.circular(24),
borderSide: BorderSide.none,
),
focusedBorder: OutlineInputBorder( // 焦点状态
borderRadius: BorderRadius.circular(24),
borderSide: BorderSide(color: Colors.blue, width: 2),
),
),
)输入格式限制
dart
TextField(
inputFormatters: [
FilteringTextInputFormatter.digitsOnly, // 仅数字
LengthLimitingTextInputFormatter(11), // 最多 11 位
FilteringTextInputFormatter.allow(RegExp(r'[a-zA-Z]')), // 仅字母
FilteringTextInputFormatter.deny(RegExp(r'[\s]')), // 禁止空格
],
)数字输入框
dart
TextField(
keyboardType: TextInputType.numberWithOptions(decimal: true), // 小数键盘
decoration: InputDecoration(
labelText: '金额',
prefixText: '¥ ', // 前缀文字
),
)常见错误
1. controller 未 dispose 导致内存泄漏
dart
// ❌ 错误:未释放 controller
class MyWidget extends StatefulWidget { ... }
_MyWidgetState extends State<MyWidget> {
final controller = TextEditingController();
// 忘记 dispose
}
// ✅ 修复:在 dispose 中释放
class _MyWidgetState extends State<MyWidget> {
final controller = TextEditingController();
@override
void dispose() {
controller.dispose(); // 必须释放
super.dispose();
}
}2. initialValue 与 controller 冲突
dart
// ❌ 错误:同时使用 initialValue 和 controller
TextFormField(
initialValue: '初始值',
controller: controller, // controller 会覆盖 initialValue
)
// ✅ 修复:二选一
TextFormField(initialValue: '初始值'), // 简单场景
// 或
TextFormField(controller: TextEditingController(text: '初始值')), // 需要控制3. 表单验证不生效
dart
// ❌ 错误:直接调用 validator
textFormFieldKey.currentState!.validate();
// ✅ 修复:使用 Form 的 validate
formKey.currentState!.validate();