Flutter键盘控制插件keyboard_invoker的使用
Flutter键盘控制插件keyboard_invoker的使用
keyboard_invoker
是一个 Flutter 插件,允许你录制按键并在主机操作系统上重新播放。
功能
- 录制和重放按键:轻松录制一系列键盘按键,并在需要时重新播放。
- 转换为MacroMap:将一系列
LogicalKeyboardKey
转换为MacroMap
,以便后续调用。
平台支持
Windows | Linux | MacOS |
---|---|---|
✔️ | ✔️ | ✔️ |
入门指南
要开始使用 keyboard_invoker
,请按照以下步骤操作:
安装
要将 keyboard_invoker
添加到你的 Flutter 项目中,在命令提示符中打开你的项目文件夹并运行以下命令:
flutter pub add keyboard_invoker
在Linux上设置
要在Linux上开始使用,你需要安装 xdotool
并配置你的显示服务器以使用 X11
。
安装 xdotool
要安装 xdotool
,打开终端并运行以下命令:
sudo apt-get install xdotool
配置显示服务器(适用于Ubuntu 22.04)
对于Ubuntu 22.04,你还需要调整显示服务器设置。为此,请执行以下命令:
sudo nano /etc/gdm3/custom.conf
找到 WaylandEnable=false
这一行,如果有必要则取消注释,保存更改,然后重启系统以使设置生效。
在MacOS上设置
在MacOS上设置更为简单,因为不需要安装任何额外软件。然而,当你尝试调用宏时,系统会提示你授予键盘输入监控权限。
请注意,此插件在MacOS上的调试模式下无法与Flutter应用一起工作。你需要构建一个发布版本才能使其正常运行,仅限于MacOS。
使用/示例
我们将使用 Provider
包来跟踪 KeyboardInvoker
的状态。
以下是一个简短示例:
// ChangeNotifierProvider 不需要作为应用的根组件
void main() {
final _keyboardInvokerPlugin = KeyboardInvoker();
runApp(
ChangeNotifierProvider(
create: (_) => _keyboardInvokerPlugin,
child: const MyApp(),
),
);
}
然后,你可以在构建方法中这样访问它:
[@override](/user/override)
Widget build(BuildContext context) {
final keyboardInvokerPlugin = Provider.of<KeyboardInvoker>(context);
...
}
录制按键序列
ElevatedButton(
onPressed: keyboardInvokerPlugin.isRecording
? () async {
// 停止录制
await keyboardInvokerPlugin.stopRecording();
}
: () async {
// 开始录制
await keyboardInvokerPlugin.startRecording();
},
child: keyboardInvokerPlugin.isRecording
? const Text("停止宏录制")
: const Text("开始宏录制")
)
调用录制的按键序列
ElevatedButton(
onPressed: () async {
try {
// 停止录制
await keyboardInvokerPlugin.stopRecording();
// 调用录制的宏
await keyboardInvokerPlugin.invokeMacroList(
keyboardInvokerPlugin.recordedKeys,
);
} catch (e) {
String errorMessage = '';
if (e is X11NotActiveInstalled) {
errorMessage = e.message;
} else if (e is XdotoolNotInstalled) {
errorMessage = e.message;
} else {
errorMessage = '发生错误: ${e.toString()}';
}
// 使用捕获的上下文显示对话框
showAboutDialog(
context: context,
children: [
Text('调用宏时出错: $errorMessage'),
],
);
}
},
child: const Text("调用已录制的宏"),
)
调用 LogicalKeyList
// 用于在主机操作系统上调用的一系列 LogicalKeyboardKey
final List<LogicalKeyboardKey> keyboardKeyList = [
LogicalKeyboardKey.shiftLeft,
LogicalKeyboardKey.keyH,
LogicalKeyboardKey.keyI,
];
ElevatedButton(
onPressed: () async {
try {
// 停止录制
await keyboardInvokerPlugin.stopRecording();
// 将宏列表转换为映射列表
List<Map<String, dynamic>> macroList =
await keyboardInvokerPlugin
.logicalKeyboardKeysToMacro(keyboardKeyList);
// 调用录制的宏
await keyboardInvokerPlugin.invokeMacroList(
macroList,
);
} catch (e) {
String errorMessage = '';
if (e is X11NotActiveInstalled) {
errorMessage = e.message;
} else if (e is XdotoolNotInstalled) {
errorMessage = e.message;
} else {
errorMessage = '发生错误: ${e.toString()}';
}
// 使用捕获的上下文显示对话框
showAboutDialog(
context: context,
children: [
Text('调用宏时出错: $errorMessage'),
],
);
}
},
child: const Text("调用测试宏"),
)
贡献
我们欢迎对 keyboard_invoker
的贡献。如果你遇到问题或有功能请求,请在GitHub上打开一个issue。
许可证
该插件根据MIT许可证发布。
示例代码
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:keyboard_invoker/keyboard_invoker.dart';
import 'package:provider/provider.dart';
void main() {
runApp(
const MyApp(),
);
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
title: 'Keyboard_invoker示例',
home: Scaffold(
appBar: AppBar(
title: const Text('Keyboard_invoker示例'),
),
// 使用provider
body: ChangeNotifierProvider<KeyboardInvoker>(
create: (context) {
return KeyboardInvoker();
},
child: const KeyboardInvokerExample(),
),
),
);
}
}
class KeyboardInvokerExample extends StatefulWidget {
const KeyboardInvokerExample({super.key});
[@override](/user/override)
State<KeyboardInvokerExample> createState() => _KeyboardInvokerExampleState();
}
class _KeyboardInvokerExampleState extends State<KeyboardInvokerExample> {
late FocusNode _focusNode;
final macroRecordingScrollController = ScrollController();
[@override](/user/override)
void initState() {
super.initState();
_focusNode = FocusNode();
}
[@override](/user/override)
void dispose() {
_focusNode.dispose();
macroRecordingScrollController.dispose();
super.dispose();
}
// 这是LogicalKeyboardKey列表
List<LogicalKeyboardKey> keyboardKeyList = [
LogicalKeyboardKey.shiftLeft,
LogicalKeyboardKey.keyB,
LogicalKeyboardKey.keyR,
LogicalKeyboardKey.keyA,
LogicalKeyboardKey.keyT,
LogicalKeyboardKey.keyW,
LogicalKeyboardKey.keyU,
LogicalKeyboardKey.keyR,
LogicalKeyboardKey.keyS,
LogicalKeyboardKey.keyT,
LogicalKeyboardKey.space,
LogicalKeyboardKey.keyU,
LogicalKeyboardKey.keyN,
LogicalKeyboardKey.keyD,
LogicalKeyboardKey.space,
LogicalKeyboardKey.keyE,
LogicalKeyboardKey.keyI,
LogicalKeyboardKey.keyN,
LogicalKeyboardKey.space,
LogicalKeyboardKey.keyG,
LogicalKeyboardKey.keyR,
LogicalKeyboardKey.keyO,
LogicalKeyboardKey.keyS,
LogicalKeyboardKey.keyS,
LogicalKeyboardKey.keyE,
LogicalKeyboardKey.keyS,
LogicalKeyboardKey.space,
LogicalKeyboardKey.keyB,
LogicalKeyboardKey.keyI,
LogicalKeyboardKey.keyE,
LogicalKeyboardKey.keyR,
];
[@override](/user/override)
Widget build(BuildContext context) {
final keyboardInvokerPlugin = Provider.of<KeyboardInvoker>(context);
return Padding(
padding: const EdgeInsets.all(15),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
if (Platform.isLinux) ...[
Text("是否为X11: ${keyboardInvokerPlugin.isX11}"),
Text(
"是否安装了xdotool: ${keyboardInvokerPlugin.isXdotoolInstalled}"),
],
Text("正在录制: ${keyboardInvokerPlugin.isRecording}"),
],
),
TextField(
focusNode: _focusNode,
decoration: const InputDecoration(
border: OutlineInputBorder(),
labelText: '测试字段',
),
),
Expanded(
child: SingleChildScrollView(
controller: macroRecordingScrollController,
child: Column(
children: keyboardInvokerPlugin.recordedKeys
.map((e) => Text(
"键: ${e["keyLabel"]} 代码: ${e["keyCode"]} 事件: ${e["event"]} 修饰符: ${e["modifiers"]}",
style: const TextStyle(fontSize: 20),
))
.toList(),
),
),
),
// 测试按钮
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
ElevatedButton(
onPressed: keyboardInvokerPlugin.isRecording
? () async {
// 停止录制
await keyboardInvokerPlugin.stopRecording();
}
: () async {
// 开始录制
await keyboardInvokerPlugin.startRecording();
},
child: keyboardInvokerPlugin.isRecording
? const Text("停止宏录制")
: const Text("开始宏录制"),
),
ElevatedButton(
onPressed: () {
// 清除录制的宏
keyboardInvokerPlugin.recordedKeys = [];
},
child: const Text("清除已录制的宏"),
),
ElevatedButton(
onPressed: () async {
// 焦点移到文本字段
_focusNode.requestFocus();
try {
// 停止录制
await keyboardInvokerPlugin.stopRecording();
// 调用录制的宏
await keyboardInvokerPlugin.invokeMacroList(
keyboardInvokerPlugin.recordedKeys,
);
} catch (e) {
String errorMessage = '';
if (e is X11NotActiveInstalled) {
errorMessage = e.message;
} else if (e is XdotoolNotInstalled) {
errorMessage = e.message;
} else {
errorMessage = '发生错误: ${e.toString()}';
}
// 使用捕获的上下文显示对话框
showAboutDialog(
context: context,
children: [
Text('调用宏时出错: $errorMessage'),
],
);
}
},
child: const Text("调用已录制的宏"),
),
ElevatedButton(
onPressed: () async {
// 焦点移到文本字段
_focusNode.requestFocus();
try {
// 停止录制
await keyboardInvokerPlugin.stopRecording();
// 将宏列表转换为映射列表
List<Map<String, dynamic>> macroList =
await keyboardInvokerPlugin
.logicalKeyboardKeysToMacro(keyboardKeyList);
// 调用录制的宏
await keyboardInvokerPlugin.invokeMacroList(
macroList,
);
} catch (e) {
String errorMessage = '';
if (e is X11NotActiveInstalled) {
errorMessage = e.message;
} else if (e is XdotoolNotInstalled) {
errorMessage = e.message;
} else {
errorMessage = '发生错误: ${e.toString()}';
}
// 使用捕获的上下文显示对话框
showAboutDialog(
context: context,
children: [
Text('调用宏时出错: $errorMessage'),
],
);
}
},
child: const Text("调用测试宏"),
),
],
),
],
),
);
}
}
更多关于Flutter键盘控制插件keyboard_invoker的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter键盘控制插件keyboard_invoker的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
keyboard_invoker
是一个 Flutter 插件,用于在 Flutter 应用中实现键盘快捷键的功能。通过这个插件,你可以为你的应用添加快捷键支持,使用户能够通过键盘操作与应用进行交互。
安装插件
首先,你需要在 pubspec.yaml
文件中添加 keyboard_invoker
插件的依赖:
dependencies:
flutter:
sdk: flutter
keyboard_invoker: ^0.0.1 # 请检查最新版本
然后运行 flutter pub get
来安装插件。
使用 keyboard_invoker
1. 导入插件
在你的 Dart 文件中导入 keyboard_invoker
插件:
import 'package:keyboard_invoker/keyboard_invoker.dart';
2. 添加快捷键
你可以使用 KeyboardInvoker
类来添加快捷键。以下是一个简单的示例,展示了如何在按下 Ctrl + S
时执行一个操作:
import 'package:flutter/material.dart';
import 'package:keyboard_invoker/keyboard_invoker.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: KeyboardInvoker(
bindings: {
LogicalKeySet(LogicalKeyboardKey.control, LogicalKeyboardKey.keyS): () {
print('Ctrl + S pressed!');
},
},
child: Scaffold(
appBar: AppBar(
title: Text('Keyboard Invoker Example'),
),
body: Center(
child: Text('Press Ctrl + S to see the effect.'),
),
),
),
);
}
}
3. 解释代码
KeyboardInvoker
是一个小部件,它包裹了你的应用内容,并监听键盘事件。bindings
参数是一个Map<LogicalKeySet, VoidCallback>
,用于定义快捷键和执行的操作。LogicalKeySet
用于表示一组按键组合。例如,LogicalKeySet(LogicalKeyboardKey.control, LogicalKeyboardKey.keyS)
表示Ctrl + S
。
4. 处理更多的快捷键
你可以为不同的按键组合定义不同的操作。例如:
KeyboardInvoker(
bindings: {
LogicalKeySet(LogicalKeyboardKey.control, LogicalKeyboardKey.keyS): () {
print('Ctrl + S pressed!');
},
LogicalKeySet(LogicalKeyboardKey.alt, LogicalKeyboardKey.keyA): () {
print('Alt + A pressed!');
},
},
child: Scaffold(
appBar: AppBar(
title: Text('Keyboard Invoker Example'),
),
body: Center(
child: Text('Press Ctrl + S or Alt + A to see the effect.'),
),
),
)