焦点与文本字段
焦点在文本字段中是如何运作的。
当一个文本字段被选中并接收输入时,即表示它拥有了“焦点”。通常情况下,用户通过点击来切换文本字段的焦点,而开发者则通过本指南中描述的工具以编程方式切换焦点。
管理焦点是构建具有直观交互流程表单的基本工具。例如,假设你有一个带有文本字段的搜索界面。当用户导航到该搜索界面时,你可以将焦点设置在该搜索词文本字段上。这样,用户无需手动点击文本字段,即可在界面可见时立即开始输入。
在本指南中,你将学习如何在文本字段可见时立即为其分配焦点,以及如何在点击按钮时为文本字段分配焦点。
在文本字段可见时立即获取焦点
#若要使文本字段在可见时立即获得焦点,请使用 autofocus 属性。
TextField(
autofocus: true,
);
有关处理输入和创建文本字段的更多信息,请参阅 Cookbook 中的 表单 (Forms) 部分。
在点击按钮时获取文本字段焦点
#有时你可能不需要立即将焦点切换到某个特定的文本字段,而是在稍后的时间点进行操作。在实际开发中,你可能还需要在 API 调用或验证错误发生时,将焦点赋予特定的文本字段。在此示例中,请按照以下步骤,在用户按下按钮后为文本字段分配焦点:
- 创建一个
FocusNode。 - 将
FocusNode传递给TextField。 - 在点击按钮时使
TextField获取焦点。
1. 创建一个 FocusNode
#
首先,创建一个 FocusNode。使用 FocusNode 在 Flutter 的“焦点树”中标识特定的 TextField。这使你能够在后续步骤中为该 TextField 分配焦点。
由于焦点节点是长生命周期对象,请使用 State 对象来管理其生命周期。请遵循以下说明,在 State 类的 initState() 方法中创建 FocusNode 实例,并在 dispose() 方法中将其销毁:
// 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> {
// Define the focus node. To manage the lifecycle, create the FocusNode in
// the initState method, and clean it up in the dispose method.
late FocusNode myFocusNode;
@override
void initState() {
super.initState();
myFocusNode = FocusNode();
}
@override
void dispose() {
// Clean up the focus node when the Form is disposed.
myFocusNode.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
// Fill this out in the next step.
}
}
2. 将 FocusNode 传递给 TextField
#
现在你已经有了 FocusNode,请在 build() 方法中将其传递给指定的 TextField。
@override
Widget build(BuildContext context) {
return TextField(focusNode: myFocusNode);
}
3. 在点击按钮时使 TextField 获取焦点
#
最后,当用户点击浮动操作按钮时,让文本字段获取焦点。使用 requestFocus() 方法来执行此任务。
FloatingActionButton(
// When the button is pressed,
// give focus to the text field using myFocusNode.
onPressed: () => myFocusNode.requestFocus(),
),
互动示例
#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: 'Text Field Focus', 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> {
// Define the focus node. To manage the lifecycle, create the FocusNode in
// the initState method, and clean it up in the dispose method.
late FocusNode myFocusNode;
@override
void initState() {
super.initState();
myFocusNode = FocusNode();
}
@override
void dispose() {
// Clean up the focus node when the Form is disposed.
myFocusNode.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Text Field Focus')),
body: Padding(
padding: const EdgeInsets.all(16),
child: Column(
children: [
// The first text field is focused on as soon as the app starts.
const TextField(autofocus: true),
// The second text field is focused on when a user taps the
// FloatingActionButton.
TextField(focusNode: myFocusNode),
],
),
),
floatingActionButton: FloatingActionButton(
// When the button is pressed,
// give focus to the text field using myFocusNode.
onPressed: () => myFocusNode.requestFocus(),
tooltip: 'Focus Second Text Field',
child: const Icon(Icons.edit),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
}