需求:需要控制表单输入的焦点

效果图如下:

代码如下:


class FocusScopeExample extends StatefulWidget {
  const FocusScopeExample({super.key});

  @override
  State<FocusScopeExample> createState() => _FocusScopeExampleState();
}

class _FocusScopeExampleState extends State<FocusScopeExample> {
  // 定义两个焦点节点
  final FocusNode _focusNode1 = FocusNode();
  final FocusNode _focusNode2 = FocusNode();

  @override
  void dispose() {
    // 释放焦点节点
    _focusNode1.dispose();
    _focusNode2.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: EdgeInsets.all(20),
      child: Column(
        children: [
          // 创建一个 FocusScope widget,包含两个文本输入框
          FocusScope(
            // 监听焦点变化
            onFocusChange: (hasFocus) {
              if (hasFocus) {
                print('第一个输入框获得焦点');
              } else {
                print('第一个输入框失去焦点');
              }
            },
            // 监听键盘按下事件
            onKeyEvent: (node, event) {
              if (event is KeyDownEvent) {
                // 处理原始键盘事件
                print('按下了键onKeyEvent:${event.logicalKey.debugName}');
                // 如果按下的是 Enter 键,则切换焦点到第二个输入框
                if (event.logicalKey == LogicalKeyboardKey.enter) {
                  FocusScope.of(context).requestFocus(_focusNode2);
                  return KeyEventResult.handled; // 表示事件已处理
                }
              }
              return KeyEventResult.ignored; // 表示事件未处理
            },
            child: Column(
              children: [
                // 第一个 TextField
                TextField(
                  focusNode: _focusNode1,
                  decoration: const InputDecoration(labelText: '输入框 1'),
                ),
                SizedBox(height: 20),
                TextField(
                  focusNode: _focusNode2,
                  decoration: const InputDecoration(labelText: '输入框 2'),
                ),
                SizedBox(height: 20),

                Row(
                  mainAxisSize: MainAxisSize.min,
                  children: [
                    ElevatedButton(
                      onPressed: () {
                        FocusScope.of(context).requestFocus(_focusNode1);
                      },
                      child: Text('切换道第一个输入框'),
                    ),
                    SizedBox(width: 20),
                    ElevatedButton(
                      onPressed: () {
                        FocusScope.of(context).requestFocus(_focusNode2);
                      },
                      child: Text('切换道第二个输入框'),
                    ),
                  ],
                ),

                // 按钮,用来切换焦点
              ],
            ),
          ),
        ],
      ),
    );
  }
}

代码解析:

  1. FocusNode:FocusNode用于标识文本框的焦点状态。在这个例子中,我们创建了两个FocusNode对象:_focusNode1_focusNode2,分别绑定到两个TextField上。
  2. FocusScope:FocusScope用来管理焦点。在这个例子中,FocusScope包含了两个TextField,这样可以通过FocusScope.of(context)来请求切换焦点。
  3. requestFocus:按钮点击事件中调用了FocusScope.of(context).requestFocus(_focusNode2),这会将焦点切换到第二个TextField
  4. dispose:dispose方法中,释放了FocusNode对象,避免内存泄漏。
  5. onFocusChange:监听焦点变化。
  6. onKeyEvent:监听键盘按下事件。event.logicalKey返回按下键的名称;KeyEventResult.handled表示事件已处理;KeyEventResult.ignored表示事件忽略;

qngyun1029
980 声望15 粉丝