TextEditingController可以在任何widget中使用
Flutter 中的 TextEditingController 可以在任何 Widget 里使用,前提是你自己正确地创建和销毁它。
TextEditingController 是一个独立的控制器对象,用来管理 EditableText/ TextField / TextFormField 的输入内容。
TextField是一个独立的输入框,不会参与 Form 的统一管理。- **
TextFormField**是FormField<String>的一个封装,专门用于文本输入,参与 Form 的统一管理,支持validator/onSaved/reset()。 EditableText其实是 TextField 的底层实现类(TextField内部就是包了一层EditableText)。
它不是依赖某个特定 Widget 的内置东西,而是你自己创建的一个 Dart 类实例。所以理论上StatelessWidget,StatefulWidget,GetxController,Provider,甚至 main() 里都可以创建和使用它。
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return const MaterialApp(home: CounterPage());
}
}
class CounterPage extends StatefulWidget {
const CounterPage({super.key});
@override
State<CounterPage> createState() => _CounterPageState();
}
class _CounterPageState extends State<CounterPage> {
// 创建 TextEditingController,但不用在任何 TextField 里
final TextEditingController _controller = TextEditingController(text: "0");
@override
void initState() {
super.initState();
// 监听内容变化
_controller.addListener(() {
debugPrint("文本内容改变为: ${_controller.text}");
});
}
@override
void dispose() {
_controller.dispose(); // 记得释放资源
super.dispose();
}
void _increment() {
// 手动修改 controller 中的文本
final current = int.tryParse(_controller.text) ?? 0;
_controller.text = (current + 1).toString();
setState(() {}); // 触发重建显示新值
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Controller 计数器')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'当前值:${_controller.text}', // 从 controller 读取内容显示
style: const TextStyle(fontSize: 24),
),
const SizedBox(height: 20),
ElevatedButton(onPressed: _increment, child: const Text('增加')),
],
),
),
);
}
}
I/flutter (17703): 文本内容改变为: 1
I/flutter (17703): 文本内容改变为: 2
I/flutter (17703): 文本内容改变为: 3
I/flutter (17703): 文本内容改变为: 4
监听器什么时候触发
只有当
controller.text发生变化时,这个监听才会被触发。换句话说:
_controller.addListener(() { print(_controller.text); });表示当
_controller内部的值(即text)发生变化时,就执行这个回调函数。
TextEditingController的text的变化
TextEditingController 本身只是一个文本状态容器,它并不会自己去“生成”文字,文字必须来自两种途径:①主动赋值(代码里设置);②用户在输入控件中输入(例如 EditableText/TextField / TextFormField 绑定了这个 controller)
自动获取(输入组件)
只要把 TextEditingController 传给输入类组件的 controller 属性:
输入类组件包括:EditableText / TextField / TextFormField
用户在界面中输入 → 会自动更新
controller.text每次
text被更新时都会notifyListeners()→ 触发你用addListener()注册的回调
import 'package:flutter/material.dart';
void main() {
runApp(const MaterialApp(home: MyEditableDemo()));
}
class MyEditableDemo extends StatefulWidget {
const MyEditableDemo({super.key});
@override
State<MyEditableDemo> createState() => _MyEditableDemoState();
}
class _MyEditableDemoState extends State<MyEditableDemo> {
final _controller = TextEditingController();
@override
void initState() {
super.initState();
// 监听内容变化
_controller.addListener(() {
print('当前输入内容:${_controller.text}');
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text("EditableText Demo")),
body: Center(
child: Container(
// 用 Container 包裹,方便设置边框和内边距
padding: const EdgeInsets.all(8),
width: 250,
// 设置边框
decoration: BoxDecoration(
// 灰色边框,圆角
border: Border.all(color: Colors.grey),
borderRadius: BorderRadius.circular(8),
),
child: EditableText(
// controller 管理输入内容
controller: _controller,
focusNode: FocusNode(),
// 设置文本样式
style: const TextStyle(color: Colors.black, fontSize: 20),
// 设置光标颜色
cursorColor: Colors.blue,
// 设置背景光标颜色
backgroundCursorColor: Colors.grey,
),
),
),
);
}
}
// 日志
I/flutter (18118): 当前输入内容:f
I/flutter (18118): 当前输入内容:ff
I/flutter (18118): 当前输入内容:fff
I/flutter (18118): 当前输入内容:ffff
I/flutter (18118): 当前输入内容:fffff
I/flutter (18118): 当前输入内容:ffffff
I/flutter (18118): 当前输入内容:fffffff
手动设置(非输入组件)
当我们绑定的是非输入类组件时(如 ElevatedButton、Text 等)时,它们本身不会改变 controller.text,所以:
- 用户点击按钮或显示文本时,不会触发
addListener() - 如果想要触发监听器,需要你在事件里手动给
controller.text赋值:
void _increment() {
// 手动修改 controller 中的文本
final current = int.tryParse(_controller.text) ?? 0;
_controller.text = (current + 1).toString();
setState(() {}); // 触发重建显示新值
}
// 用户需要配合onPressed函数,给TextEditingController的text赋值
ElevatedButton(onPressed: _increment, child: const Text('增加')),
// _controller.text 变化之后,才会触发监听器
_controller.addListener(() {
debugPrint("文本内容改变为: ${_controller.text}");
});
也就是说,这类组件 必须「手动更新 controller」,监听器才会被调用。