處理文字欄位的更改
如何檢測文字欄位的變更。
在某些情況下,每當文字欄位中的文字發生變化時執行回撥函式會很有用。例如,你可能想要構建一個具有自動完成功能的搜尋介面,並希望在使用者輸入時更新搜尋結果。
如何實現每當文字更改時執行回撥函式?在 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),
],
),
),
);
}
}