7

I'm writing a Flutter app and want to handle keyboard shortcuts like Ctrl+I in the web version of the app.

Small disclaimer: Looks like the Flutter API around shortcuts has changed recently. The online documentation that I found was outdated. I'm using Flutter 1.19.0-0.0.pre • channel dev.

I found the Actions API Design document which feels like the current available API. Based on the example in the document I implemented this short snippet:

class MyIntent extends Intent {}

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: Shortcuts(
        shortcuts: {
          LogicalKeySet(LogicalKeyboardKey.control): MyIntent(),
        },
        child: Actions(
          actions: {
            MyIntent: CallbackAction(onInvoke: (i) {
              print('Hello World!!!');
              return null;
            }),
          },
          child: Center(
            child: Column(
              children: <Widget>[
                Text(
                  'Hello World',
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

However, it does not react on pressing the control-key and does not output the expected message. While debugging into the code I noticed that the instance of ShortcutManager that does handle the key event does not contain my key combination as specified, but nine other key combinations.

Does anybody know, how to use the Shortcuts and Actions API to react on keyboard shortcuts?

Fox32
  • 13,126
  • 9
  • 50
  • 71

2 Answers2

5

In your example, you have the right idea, but what you're missing is a Focus widget. If the widget doesn't have focus, then its ancestor Shortcuts widget won't receive the key event in order to handle it.

See this Dartpad example to see what I mean. The example adds a new "Homework" when the "Alt+N" keys are pressed.

You can also use the FocusableActionDetector which combines Shortcuts, Actions, and mouse hover handling into one widget.

Greg
  • 224
  • 3
  • 10
  • the dartpad example worked fine for me, but is there any way to detect when the keys are released? I am unable to wrap `RawKeyboardListener` around `FocusableActionDetector ` to get the latest keyup/down event as it is throwing `'!ancestors.contains(child)': The supplied child is already an ancestor of this node. Loops are not allowed` error. How do I listen the latest keypress events when I am using `FocusableActionDetector` or `Shortcuts`? – Ganesh Rathinavel Jan 20 '21 at 14:40
  • It's strange how they used Intent here, like it's a pretty useless class and kinda annoying. This is not very "flutter", seems over engineered. – Oliver Dixon May 10 '22 at 15:30
0

I want to add something in the above answer(https://stackoverflow.com/a/63622833/162802020):

If you want to add more than one key in a single shortcut, then your code will be:

            shortcuts: <ShortcutActivator, Intent> {
          LogicalKeySet(LogicalKeyboardKey.control, LogicalKeyboardKey.keyL): MyIntent(),
      },