焦点和文本框

当一个文本框(输入框)被选中并接受输入时,被称为获得了“焦点”。通常情况下,用户能够通过点击文本框以使其聚焦,开发人员也可以使用本文所描述的方法来让文本框得到焦点。

管理焦点是一种直观地创建表单流程的基本方法。例如,假设我们有一个带有文本框的搜索页面。当用户导航到搜索页面时,我们可以聚焦文本框的搜索项。这将允许用户在搜索页面可见时能够立即开始输入,而无需手动点击文本框。

在本文中,我们将学习如何聚焦到文本框上,以及点击按钮时聚焦文本框。

一旦文本框可见,就将其聚焦

#

为了在文本框可见时将其聚焦,我们可以使用 autofocus 属性。

dart
TextField(
  autofocus: true,
);

有关处理输入和创建文本框的更多信息,请参阅 实用教程的 Forms 部分

点击按钮时聚焦文本框

#

我们也可能需要在之后的某个时间点聚焦特定的文本框,而不是立即聚焦它。在这个例子中,我们将看到在用户按下按钮后如何聚焦文本框。在实际开发中,你还可能需要聚焦特定的文本框以响应 api 调用或错误校验。

  1. 创建一个 FocusNode

  2. FocusNode 传递给 TextField

  3. 通过点击按钮聚焦 TextField

1. 创建一个 FocusNode

#

首先,我们需要创建一个 FocusNode。我们将使用 FocusNode 来识别 Flutter 的“focus tree”中的特定的 TextField。这将允许我们能够在接下来的步骤中聚焦 TextField

由于 focus node 是长寿命对象,我们需要使用 State 类来管理生命周期。为此,需要在 State 类的 initState 方法中创建 FocusNode 实例,并在 dispose 方法中清除它们。

dart
// 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,我们可以将这个 TextField 传递给 build() 方法。

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

3. 通过点击按钮聚焦 TextField

#

最后,当用户点击 floating action button 时,我们将要聚焦文本框!为此我们将要使用 requestFocus() 方法来完成此操作。

dart
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.
    );
  }
}