Flutter焦点控制插件focusable_control_builder的使用

发布于 1周前 作者 itying888 来自 Flutter

Flutter焦点控制插件focusable_control_builder的使用

使用FocusableControlBuilder可以快速创建一个在所有平台和输入设备上都能正常工作的控件。

工作“正常”包括支持以下功能:

  • Tab键遍历
  • 聚焦/悬停状态
  • 修改鼠标光标
  • 支持键盘快捷键(默认为Enter/空格键)

在内部,该构建器包装了内置的FocusableActionDetector,你可以在这里了解更多关于其工作原理的细节。

有关为何要使用这些小部件的更多信息,请参阅此博客文章: https://blog.gskinner.com/archives/2021/06/flutter-building-custom-components-with-focusableactiondetector.html

🔨 安装

$ flutter pub add focusable_control_builder

⚙ 导入

import 'package:focusable_control_builder/focusable_control_builder.dart';

🕹️ 使用

要创建一个自定义按钮,只需实现FocusableControlBuilder.builder方法,并分配一个onPressed处理程序:

class MyCustomButton extends StatelessWidget {
  const MyCustomButton(this.label, {Key? key, required this.onPressed}) : super(key: key);
  final String label;
  final VoidCallback onPressed;

  [@override](/user/override)
  Widget build(BuildContext context) {
    return FocusableControlBuilder(
        onPressed: onPressed,
        builder: (_, FocusableControlState control) {
          // 根据 .isFocused 和 .isHovered 决定使用哪种颜色
          Color outlineColor = control.isFocused ? Colors.black : Colors.transparent;
          Color bgColor = control.isHovered ? Colors.blue.shade100 : Colors.grey.shade200;
          // 返回自定义按钮内容
          return Container(
            padding: const EdgeInsets.all(8),
            child: Text(label),
            decoration: BoxDecoration(
              color: bgColor,
              border: Border.all(color: outlineColor, width: 1),
            ),
          );
        });
  }
}

自定义鼠标光标

FocusableControlBuilder 默认会为你控件设置一个“手型”光标。如果你想要不同的光标,只需分配它:

return FocusableControlBuilder(
    cursor: SystemMouseCursors.resizeDown,
    ...
);

请求聚焦

FocusableControlBuilder 默认会在按下时请求聚焦。如果你想禁用这个功能,只需将其设置为 false

return FocusableControlBuilder(
    requestFocusOnPress: false,
    ...
);

自定义快捷键

FocusableControlBuilder 会创建一个默认激活动作,处理 [提交][Enter] 键。若要创建自定义键盘快捷键,可以设置 .shortcuts.actions 参数。这超出了本文档的范围,但如果你想了解如何操作,可以查看 FocusableActionDetector 文档,其中包含一个示例。

🐞 Bug/需求

如果你遇到任何问题,请打开一个issue。如果你觉得库缺少功能,请在Github上提出一个ticket,我们会进行评估。欢迎提交pull request。

📃 许可证

MIT许可证


以下是完整的示例代码:

import 'package:example/custom_button.dart';
import 'package:example/custom_checkbox.dart';
import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  [@override](/user/override)
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: Scaffold(
        body: CustomButtonsAndCheckboxesDemo(),
      ),
    );
  }
}

class CustomButtonsAndCheckboxesDemo extends StatefulWidget {
  const CustomButtonsAndCheckboxesDemo({Key? key}) : super(key: key);

  [@override](/user/override)
  State<CustomButtonsAndCheckboxesDemo> createState() => _CustomButtonsAndCheckboxesDemoState();
}

class _CustomButtonsAndCheckboxesDemoState extends State<CustomButtonsAndCheckboxesDemo> {
  bool _check1 = false;
  bool _check2 = true;
  bool _check3 = false;

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Center(
      child: Column(
        mainAxisSize: MainAxisSize.min,
        children: [
          const Text("使用 'Tab' 键遍历按钮。使用 Enter/空格键来点击它们。"),
          Row(
            mainAxisSize: MainAxisSize.min,
            children: [
              const CustomButton("按钮 1"),
              CustomButton("按钮 2", onPressed: () => debugPrint("点击2")),
              CustomButton("按钮 3", onPressed: () => debugPrint("点击3")),
            ],
          ),
          const SizedBox(height: 30),
          CustomCheckbox("复选框1", value: _check1, onChanged: (v) => setState(() => _check1 = v)),
          CustomCheckbox("复选框2", value: _check2, onChanged: (v) => setState(() => _check2 = v)),
          CustomCheckbox("复选框3", value: _check3, onChanged: (v) => setState(() => _check3 = v)),
        ],
      ),
    );
  }
}

更多关于Flutter焦点控制插件focusable_control_builder的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter焦点控制插件focusable_control_builder的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


在Flutter中,focusable_control_builder 插件可以帮助你更精细地控制焦点(Focus)在UI组件之间的移动。尽管这个插件不是官方的Flutter包,但假设它是一个自定义的或者社区维护的包,我们可以通过一些示例代码来展示如何使用它。

首先,确保你已经在pubspec.yaml文件中添加了该依赖项(注意,实际包名可能会有所不同,这里用focusable_control_builder作为示例):

dependencies:
  flutter:
    sdk: flutter
  focusable_control_builder: ^x.y.z  # 替换为实际版本号

然后运行flutter pub get来安装依赖。

假设focusable_control_builder提供了一个FocusableControlBuilder widget,允许你定义焦点行为,以下是一个如何使用它的示例:

import 'package:flutter/material.dart';
import 'package:focusable_control_builder/focusable_control_builder.dart'; // 假设这是正确的导入路径

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Focusable Control Builder Demo'),
        ),
        body: Padding(
          padding: const EdgeInsets.all(16.0),
          child: FocusableControlBuilder(
            // 假设这里可以定义一些焦点控制逻辑
            focusOrder: [
              'textField1',
              'textField2',
              'textField3',
            ],
            child: Column(
              children: <Widget>[
                TextField(
                  key: ValueKey('textField1'),
                  decoration: InputDecoration(labelText: 'Text Field 1'),
                ),
                TextField(
                  key: ValueKey('textField2'),
                  decoration: InputDecoration(labelText: 'Text Field 2'),
                ),
                TextField(
                  key: ValueKey('textField3'),
                  decoration: InputDecoration(labelText: 'Text Field 3'),
                ),
                ElevatedButton(
                  onPressed: () {
                    // 假设这里有一个方法可以控制焦点移动
                    // FocusController().nextFocus(); 或者类似的API
                  },
                  child: Text('Next Field'),
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

注意:上述代码中的FocusableControlBuilder及其focusOrder属性是假设性的,因为实际的focusable_control_builder插件可能有不同的API设计。你需要查阅该插件的文档来获取准确的用法。

如果focusable_control_builder提供了API来控制焦点(比如nextFocus()previousFocus()),你可以将这些方法绑定到按钮或其他交互元素上,以实现自定义的焦点控制逻辑。

由于focusable_control_builder不是Flutter官方包,具体的实现细节和API可能会有所不同。如果上述假设性的用法不符合实际插件的API,请参考该插件的官方文档或源代码以获取准确的实现方式。

回到顶部