处理文本字段的更改
如何检测文本字段的变更。
在某些情况下,每当文本字段中的文本发生变化时运行回调函数会很有用。例如,你可能想要构建一个具有自动完成功能的搜索界面,并希望在用户输入时更新搜索结果。
如何实现每当文本更改时运行回调函数?在 Flutter 中,你有两种选择:
- 为
TextField或TextFormField提供onChanged()回调。 - 使用
TextEditingController。
1. 为 TextField 或 TextFormField 提供 onChanged() 回调
#
最简单的方法是为 TextField 或 TextFormField 提供一个 onChanged() 回调。每当文本发生变化时,该回调就会被触发。
在此示例中,每当文本更改时,将文本字段的当前值和长度打印到控制台。
处理用户输入时使用 characters 非常重要,因为文本可能包含复杂的字符。这确保了每个字符都能按照用户所见被正确计数。
TextField(
onChanged: (text) {
print('First text field: $text (${text.characters.length})');
},
),
2. 使用 TextEditingController
#
一种更强大但更复杂的方案是提供一个 TextEditingController 作为 TextField 或 TextFormField 的 controller 属性。
要在文本更改时获得通知,请按照以下步骤使用 addListener() 方法监听控制器:
- 创建一个
TextEditingController。 - 将
TextEditingController连接到文本字段。 - 创建一个函数以打印最新值。
- 监听控制器的变更。
创建 TextEditingController
#
创建 TextEditingController
// Define a custom Form widget.
class MyCustomForm extends StatefulWidget {
const MyCustomForm({super.key});
@override
State<MyCustomForm> createState() => _MyCustomFormState();
}
// Define a corresponding State class.
// This class holds data related to the Form.
class _MyCustomFormState extends State<MyCustomForm> {
// Create a text controller. Later, use it to retrieve the
// current value of the TextField.
final myController = TextEditingController();
@override
void dispose() {
// Clean up the controller when the widget is removed from the
// widget tree.
myController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
// Fill this out in the next step.
}
}
将 TextEditingController 连接到文本字段
#
将 TextEditingController 提供给 TextField 或 TextFormField。将这两者关联起来后,你就可以开始监听文本字段的变更了。
TextField(controller: myController),
创建一个函数以打印最新值
#你需要一个在每次文本更改时运行的函数。在 _MyCustomFormState 类中创建一个打印文本字段当前值的方法。
void _printLatestValue() {
final text = myController.text;
print('Second text field: $text (${text.characters.length})');
}
监听控制器的变更
#最后,监听 TextEditingController 并在文本更改时调用 _printLatestValue() 方法。为此,请使用 addListener() 方法。
在初始化 _MyCustomFormState 类时开始监听变更,并在 _MyCustomFormState 被销毁时停止监听。
@override
void initState() {
super.initState();
// Start listening to changes.
myController.addListener(_printLatestValue);
}
@override
void dispose() {
// Clean up the controller when the widget is removed from the widget tree.
// This also removes the _printLatestValue listener.
myController.dispose();
super.dispose();
}
互动示例
#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(
title: 'Retrieve Text Input',
home: MyCustomForm(),
);
}
}
// Define a custom Form widget.
class MyCustomForm extends StatefulWidget {
const MyCustomForm({super.key});
@override
State<MyCustomForm> createState() => _MyCustomFormState();
}
// Define a corresponding State class.
// This class holds data related to the Form.
class _MyCustomFormState extends State<MyCustomForm> {
// Create a text controller and use it to retrieve the current value
// of the TextField.
final myController = TextEditingController();
@override
void initState() {
super.initState();
// Start listening to changes.
myController.addListener(_printLatestValue);
}
@override
void dispose() {
// Clean up the controller when the widget is removed from the widget tree.
// This also removes the _printLatestValue listener.
myController.dispose();
super.dispose();
}
void _printLatestValue() {
final text = myController.text;
print('Second text field: $text (${text.characters.length})');
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Retrieve Text Input')),
body: Padding(
padding: const EdgeInsets.all(16),
child: Column(
children: [
TextField(
onChanged: (text) {
print('First text field: $text (${text.characters.length})');
},
),
TextField(controller: myController),
],
),
),
);
}
}