Skip to main content

焦点和文本字段

当文本字段被选中并接受输入时,据说它具有“焦点”。通常,用户通过点击来将焦点切换到文本字段,而开发人员则通过使用本配方中描述的工具以编程方式将焦点切换到文本字段。

焦点管理是创建具有直观流程的表单的基本工具。例如,假设您有一个带有文本字段的搜索屏幕。当用户导航到搜索屏幕时,您可以将焦点设置到搜索词的文本字段。这允许用户在屏幕可见后立即开始键入,而无需手动点击文本字段。

在本配方中,学习如何在文本字段可见后立即将其设置为焦点,以及如何在点击按钮时将焦点赋予文本字段。

立即获取文本字段焦点

#

要在文本字段可见后立即将其设置为焦点,请使用 autofocus 属性。

dart
TextField(
  autofocus: true,
);

有关处理输入和创建文本字段的更多信息,请参阅食谱的表单部分。

点击按钮时获取文本字段焦点

#

您可能不需要立即将焦点切换到特定的文本字段,而是在稍后的时间点将焦点赋予文本字段。在现实世界中,您可能还需要响应 API 调用或验证错误来将焦点赋予特定的文本字段。在此示例中,在用户按下按钮后,请按照以下步骤将焦点赋予文本字段:

  1. 创建一个 FocusNode
  2. FocusNode 传递给 TextField
  3. 点击按钮时将焦点赋予 TextField

1. 创建 FocusNode

#

首先,创建一个 FocusNode。使用 FocusNode 在 Flutter 的“焦点树”中识别特定的 TextField。这允许您在接下来的步骤中将焦点赋予 TextField

由于焦点节点是长期存在的对象,因此请使用 State 对象管理生命周期。请使用以下说明在 State 类的 initState() 方法内创建一个 FocusNode 实例,并在 dispose() 方法中将其清理:

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

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

// 定义相应的 State 类。
// 此类保存与表单相关的数据。
class _MyCustomFormState extends State<MyCustomForm> {
  // 定义焦点节点。为了管理生命周期,在 initState 方法中创建 FocusNode,并在 dispose 方法中清理它。
  late FocusNode myFocusNode;

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

    myFocusNode = FocusNode();
  }

  @override
  void dispose() {
    // 处置表单时清理焦点节点。
    myFocusNode.dispose();

    super.dispose();
  }

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

2. 将 FocusNode 传递给 TextField

#

现在您已经有了一个 FocusNode,请将其传递给 build() 方法中的特定 TextField

dart
@override
Widget build(BuildContext context) {
  return TextField(
    focusNode: myFocusNode,
  );
}

3. 点击按钮时将焦点赋予 TextField

#

最后,当用户点击浮动操作按钮时,将焦点设置到文本字段。使用 requestFocus() 方法执行此任务。

dart
FloatingActionButton(
  // 按下按钮时,
  // 使用 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: '文本字段焦点',
      home: MyCustomForm(),
    );
  }
}

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

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

// 定义相应的 State 类。
// 此类保存与表单相关的数据。
class _MyCustomFormState extends State<MyCustomForm> {
  // 定义焦点节点。为了管理生命周期,在 initState 方法中创建 FocusNode,并在 dispose 方法中清理它。
  late FocusNode myFocusNode;

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

    myFocusNode = FocusNode();
  }

  @override
  void dispose() {
    // 处置表单时清理焦点节点。
    myFocusNode.dispose();

    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('文本字段焦点'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(16),
        child: Column(
          children: [
            // 应用程序启动后,第一个文本字段立即获得焦点。
            const TextField(
              autofocus: true,
            ),
            // 用户点击浮动操作按钮时,第二个文本字段获得焦点。
            TextField(
              focusNode: myFocusNode,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        // 按下按钮时,
        // 使用 myFocusNode 将焦点赋予文本字段。
        onPressed: () => myFocusNode.requestFocus(),
        tooltip: '将焦点设置到第二个文本字段',
        child: const Icon(Icons.edit),
      ), // 此尾随逗号使构建方法的自动格式化更漂亮。
    );
  }
}