Skip to main content

处理文本字段的更改

在某些情况下,每次文本字段中的文本发生更改时运行回调函数非常有用。例如,您可能希望构建具有自动完成功能的搜索屏幕,以便在用户键入时更新结果。

您如何每次文本更改时运行回调函数?使用 Flutter,您有两种选择:

  1. TextFieldTextFormField 提供 onChanged() 回调。
  2. 使用 TextEditingController

1. 为 TextFieldTextFormField 提供 onChanged() 回调

#

最简单的方法是为 TextFieldTextFormField 提供 onChanged() 回调。每当文本更改时,都会调用回调函数。

在此示例中,每次文本更改时,都会将文本字段的当前值和长度打印到控制台。

在处理用户输入时,使用 characters 非常重要,因为文本可能包含复杂字符。这确保了每个字符都按照用户看到的方式正确计数。

dart
TextField(
  onChanged: (text) {
    print('第一个文本字段: $text (${text.characters.length})');
  },
),

2. 使用 TextEditingController

#

更强大但更复杂的方法是提供一个 TextEditingController 作为 TextFieldTextFormFieldcontroller 属性。

要接收文本更改的通知,请使用 addListener() 方法监听控制器,步骤如下:

  1. 创建一个 TextEditingController
  2. TextEditingController 连接到文本字段。
  3. 创建一个函数来打印最新值。
  4. 监听控制器的更改。

创建 TextEditingController

#

创建一个 TextEditingController

dart
// 定义一个自定义表单小部件。
class MyCustomForm extends StatefulWidget {
  const MyCustomForm({super.key});

  @override
  State<MyCustomForm> createState() => _MyCustomFormState();
}

// 定义相应的 State 类。
// 此类保存与表单相关的数据。
class _MyCustomFormState extends State<MyCustomForm> {
  // 创建一个文本控制器。稍后,用它来检索
  // TextField 的当前值。
  final myController = TextEditingController();

  @override
  void dispose() {
    // 当小部件从
    // 小部件树中移除时清理控制器。
    myController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    // 在下一步中填写此内容。
  }
}

TextEditingController 连接到文本字段

#

TextEditingController 提供给 TextFieldTextFormField。将这两个类连接起来后,就可以开始监听文本字段的更改了。

dart
TextField(
  controller: myController,
),

创建一个函数来打印最新值

#

每次文本更改时都需要运行一个函数。在 _MyCustomFormState 类中创建一个方法,打印出文本字段的当前值。

dart
void _printLatestValue() {
  final text = myController.text;
  print('第二个文本字段: $text (${text.characters.length})');
}

监听控制器的更改

#

最后,监听 TextEditingController,并在文本更改时调用 _printLatestValue() 方法。为此,请使用 addListener() 方法。

在初始化 _MyCustomFormState 类时开始监听更改,并在释放 _MyCustomFormState 时停止监听。

dart
@override
void initState() {
  super.initState();

  // 开始监听更改。
  myController.addListener(_printLatestValue);
}
dart
@override
void dispose() {
  // 当小部件从窗口部件树中移除时清理控制器。
  // 这还会移除 _printLatestValue 监听器。
  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: '检索文本输入',
      home: MyCustomForm(),
    );
  }
}

// 定义一个自定义表单小部件。
class MyCustomForm extends StatefulWidget {
  const MyCustomForm({super.key});

  @override
  State<MyCustomForm> createState() => _MyCustomFormState();
}

// 定义相应的 State 类。
// 此类保存与表单相关的数据。
class _MyCustomFormState extends State<MyCustomForm> {
  // 创建一个文本控制器并用它来检索 TextField 的当前值。
  final myController = TextEditingController();

  @override
  void initState() {
    super.initState();

    // 开始监听更改。
    myController.addListener(_printLatestValue);
  }

  @override
  void dispose() {
    // 当小部件从窗口部件树中移除时清理控制器。
    // 这还会移除 _printLatestValue 监听器。
    myController.dispose();
    super.dispose();
  }

  void _printLatestValue() {
    final text = myController.text;
    print('第二个文本字段: $text (${text.characters.length})');
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('检索文本输入'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(16),
        child: Column(
          children: [
            TextField(
              onChanged: (text) {
                print('第一个文本字段: $text (${text.characters.length})');
              },
            ),
            TextField(
              controller: myController,
            ),
          ],
        ),
      ),
    );
  }
}