在某些情境中,我们可能需要在每次文本框的文本内容变化时都调用回调函数。例如,当构建一个有自动填充功能的搜索页面时,我们希望根据用户输入的内容来更新返回的结果。
那么如何每次在文本内容改变时调用回调函数呢?在Flutter中,我们提供了两种选择:
给
TextField绑定onChanged回调使用
TextEditingController
1. 给 TextField 绑定 onChanged 回调
最简单的方法是给 TextField 绑定 onChanged 回调。每当文本内容改变时,回调函数会被触发。但这种方法有一个缺点,它不适用于 TextFormField 组件。
在下面的示例中,每次 text 的值改变,会在控制台中打印出当前文本框的值。
TextField(onChanged: (text) {print("First text field: $text");},);
2. 使用 TextEditingController
另外一种更强大但是更复杂的方法是绑定 TextEditingController 作为 TextField 和 TextFormField 的 controller 属性
想要在文本更改时收到通知,我们可以使用 addListener 方法来监听控制器。
步骤
创建一个
TextEditingController将
TextEditingController绑定到TextField创建一个函数来打印最新值
监听控制器的变化
创建一个 TextEditingController
首先,我们需要创建一个 TextEditingController ,然后将 TextField 绑定 TextEditingController 。一旦将这两个类绑定在一起,我们就可以监听文本框的改变了!
// Define a Custom Form Widgetclass MyCustomForm extends StatefulWidget {@override_MyCustomFormState createState() => _MyCustomFormState();}// Define a corresponding State class. This class will hold the data related to// our Form.class _MyCustomFormState extends State<MyCustomForm> {// Create a text controller. We will use it to retrieve the current value// of the TextField!final myController = TextEditingController();@overridevoid dispose() {// Clean up the controller when the Widget is removed from the Widget treemyController.dispose();super.dispose();}@overrideWidget build(BuildContext context) {// We will fill this out in the next step!}}
注意:请在 TextEditingController 使用完毕时将其 dispose ,从而确保所有被这个对象所使用的资源被释放。
给 TextField 绑定 TextEditingController
TextEditingController 必须绑定到 TextField 或者是 TextFormField 才能被正常的使用。一旦绑定,就能够开始监听文本框的变化。
TextField(controller: myController,);
创建一个打印当前值的方法
现在,我们需要一个每当表单项变化都会运行的函数!在下面的示例中,我们会创建一个打印文本框当前值的方法。
这个方法将存在于 _MyCustomFormState 类中。
_printLatestValue() {print("Second text field: ${myController.text}");}
监听控制器的变化
最后,需要监听 TextEditingController 并且在 text 值变化时运行 _printLatestValue 方法。我们需要使用addListener方法来实现这个功能。
下面的示例会在类 _MyCustomFormState 初始化的时候开始监听变化,dispose 时停止监听。
class _MyCustomFormState extends State<MyCustomForm> {@overridevoid initState() {super.initState();// Start listening to changesmyController.addListener(_printLatestValue);}}
完整样例
import 'package:flutter/material.dart';void main() => runApp(MyApp());class MyApp extends StatelessWidget {@overrideWidget build(BuildContext context) {return MaterialApp(title: 'Retrieve Text Input',home: MyCustomForm(),);}}// Define a Custom Form Widgetclass MyCustomForm extends StatefulWidget {@override_MyCustomFormState createState() => _MyCustomFormState();}// Define a corresponding State class. This class will hold the data related to// our Form.class _MyCustomFormState extends State<MyCustomForm> {// Create a text controller. We will use it to retrieve the current value// of the TextField!final myController = TextEditingController();@overridevoid initState() {super.initState();myController.addListener(_printLatestValue);}@overridevoid dispose() {// Clean up the controller when the Widget is removed from the Widget tree// This also removes the _printLatestValue listenermyController.dispose();super.dispose();}_printLatestValue() {print("Second text field: ${myController.text}");}@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text('Retrieve Text Input'),),body: Padding(padding: const EdgeInsets.all(16.0),child: Column(children: <Widget>[TextField(onChanged: (text) {print("First text field: $text");},),TextField(controller: myController,),],),),);}}