Flutter桌面端开发——快捷键
hotkey_manager
该插件由LeanFlutter维护支持
安装🛠
点击hotkey_manager获取最新版本。以下是在编写本文章时的最新版本:
hotkey_manager: ^0.1.7
使用🍚
如果全局使用,需要在main方法中插入以下代码
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await hotKeyManager.unregisterAll();
runApp(MyApp());
}
如果在某个页面使用,在 initState 方法中进行操作
void initState() {
super.initState();
_init();
}
_init() async {
await hotKeyManager.unregisterAll();
}
注册快捷键
注册快捷键需要使用 hotKeyManager.register 方法。该方法可以传递3个参数:
HotKey hotKey
:快捷键对象,可以传入4个属性KeyCode keyCode
:快捷键List ? modifiers
:修饰符,Alt、Shift 等String? identifier
:标识符HotKeyScope? scope
:快捷键范围。有 HotKeyScope.system(默认) 和 HotKeyScope.inapp 两个值
void Function(HotKey)? keyDownHandler
:快捷键按下事件void Function(HotKey)? keyUpHandler
:快捷键抬起事件(仅macOS )
定义两个变量来存储按下的信息
String _message = '你还未按下任何快捷键';
int _count = 0;
_init() async {
await hotKeyManager.unregisterAll();
await hotKeyManager.register(
HotKey(KeyCode.f1),
keyDownHandler: (_) {
_count++;
_message = '按下了F1键$_count次';
setState(() {});
},
);
}
默认注册的是全局快捷键,如果你焦点不在自己的程序上,也会调用该方法
我们给快捷键加上修饰符
HotKey(KeyCode.f1, modifiers: [KeyModifier.alt]),
现在只有同时按下 Alt + F1 才会调用,无法演示我按了什么键,所以可以自己试一下。
注销快捷键
注销快捷键需要使用 hotKeyManager.unregister,为了方便管理,我们把 HotKey 对象提取出来
final _hotKey = HotKey(KeyCode.f1, modifiers: [KeyModifier.alt]);
_unregister(HotKey hotKey) async {
if (hotKeyManager.registeredHotKeyList.contains(hotKey)) {
await hotKeyManager.unregister(hotKey);
_message = '快捷键注销成功';
setState(() {});
}
}
显示快捷键
该插件中有一个组件可以显示设置的快捷键
HotKeyVirtualView(hotKey: _hotKey),
录制快捷键
插件中还有一个 HotKeyRecorder 组件可以帮我们录制快捷键。该组件一共有3个属性:
Key? key
:标识HotKey? initalHotKey
:初始快捷键void Function(HotKey) onHotKeyRecorded
:录制快捷键的方法
为了方便,我们把注册快捷键的方法提取出来更改一下
_register(HotKey hotKey) async {
await hotKeyManager.register(
hotKey,
keyDownHandler: (_) {
_count++;
if (hotKey.modifiers == null) {
_message = '按下了快捷键${hotKey.keyCode.keyLabel} $_count次';
} else {
_message = '按下了快捷键';
for (var key in hotKey.modifiers!) {
_message += '${key.keyLabel} + ';
}
_message += '${hotKey.keyCode.keyLabel} $_count次';
}
setState(() {});
},
);
hotKeyManager.registeredHotKeyList;
}
再使用 HotKeyRecorder 组件
HotKeyRecorder(
initalHotKey: _hotKey,
onHotKeyRecorded: (hotKey) {
_newHotKey = hotKey;
// _newHotKey?.scope = HotKeyScope.inapp;
setState(() {});
},
),
这里我修改了以前的快捷键,以前那个可能冲突了突然用不了
HotKey _hotKey = HotKey(KeyCode.f2, modifiers: [KeyModifier.alt]);
这里我使用一个变量来存储新建的快捷键
TextButton(
onPressed: _newHotKey == null
? () {}
: () async {
_count = 0;
_unregister(_hotKey);
_hotKey = _newHotKey!;
_register(_hotKey);
_newHotKey = null;
_message = '快捷键修改成功';
setState(() {});
},
child: const Text('更改快捷键'),
),
FocusableActionDetector
以下内容来源于《Using Keyboard Shortcuts in Flutter Desktop. A Simple Guide.》
Flutter中有一个 RawKeyboardListener 组件可以监听用户按下的键盘,但是一次只能监听一个。而FocusableActionDetector附带了一个非常简单的用于侦听键盘快捷键的 API,它接受一个快捷键(LogicalKeySet: Intent)和动作(Intent: Action)的映射。
我们先来做个简单的数字加减功能
import 'package:flutter/material.dart';
class UseFlutterWidget extends StatefulWidget {
const UseFlutterWidget({Key? key}) : super(key: key);
@override
State<UseFlutterWidget> createState() => _UseFlutterWidgetState();
}
class _UseFlutterWidgetState extends State<UseFlutterWidget> {
int _count = 0;
@override
Widget build(BuildContext context) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('$_count', style: const TextStyle(fontSize: 48)),
const SizedBox(height: 24),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton(onPressed: _increment, child: const Text('+1')),
const SizedBox(width: 24),
ElevatedButton(onPressed: _decrement, child: const Text('-1')),
],
),
],
),
);
}
void _increment() {
_count++;
setState(() {});
}
void _decrement() {
_count--;
setState(() {});
}
}
接下来就可以为这两个方法来创建快捷键了。
首先,我们需要为该方法创建快捷键和意图
final incrementKey = LogicalKeySet(
LogicalKeyboardKey.control,
LogicalKeyboardKey.arrowUp,
);
final decrementKey = LogicalKeySet(
LogicalKeyboardKey.control,
LogicalKeyboardKey.arrowDown,
);
class IncrementIntent extends Intent {}
class DecrementIntent extends Intent {}
关于Flutter中键盘按键相关的可以查看文档
创建一个计数快捷键的组件
class CounterShortcuts extends StatelessWidget {
const CounterShortcuts({
Key? key,
required this.child,
required this.onIncrementDetected,
required this.onDecrementDetected,
}) : super(key: key);
final Widget child;
final VoidCallback onIncrementDetected;
final VoidCallback onDecrementDetected;
@override
Widget build(BuildContext context) {
return FocusableActionDetector(
autofocus: true,
shortcuts: {
incrementKey: IncrementIntent(),
decrementKey: DecrementIntent(),
},
actions: {
IncrementIntent: CallbackAction(
onInvoke: (_) => onIncrementDetected.call(),
),
DecrementIntent: CallbackAction(
onInvoke: (_) => onDecrementDetected.call(),
),
},
child: child,
);
}
}
把该组件作为前面写的父组件
class _UseFlutterWidgetState extends State<UseFlutterWidget> {
int _count = 0;
@override
Widget build(BuildContext context) {
return CounterShortcuts(
onIncrementDetected: _increment,
onDecrementDetected: _decrement,
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('$_count', style: const TextStyle(fontSize: 48)),
const SizedBox(height: 24),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton(onPressed: _increment, child: const Text('+1')),
const SizedBox(width: 24),
ElevatedButton(onPressed: _decrement, child: const Text('-1')),
],
),
],
),
),
);
}
void _increment() {
_count++;
setState(() {});
}
void _decrement() {
_count--;
setState(() {});
}
}
🛫OK,以上就是这篇文章的全部内容,在使用插件前请先对照好版本,新版本可能会更改用法。本实例代码已上传至 github 和 gitee,有需要的可以下载下来查看学习。