alex smith
alex smith

Reputation: 550

Flutter FocusNode onKeyEvent detect multiple keys

Using this for Flutter Desktop. I used to use onKey of FocusNode. The doc says it will be deprecated:

  /// To receive key events that focuses on this node, pass a listener to `onKeyEvent`.
  /// The `onKey` is a legacy API based on [RawKeyEvent] and will be deprecated
  /// in the future.

This is how I used onKey for detecting shift + enter:

FocusNode(          
    onKey: (node, event)
    {
        if (event.isKeyPressed(LogicalKeyboardKey.enter))
        {
            if (event.isShiftPressed)
                return KeyEventResult.ignored;

            sendAction();
            return KeyEventResult.handled;
        }

        return KeyEventResult.ignored;
    },

How do you detect multiple keys being pressed at the same time with onKeyEvent?

Edit: I'm looking for a way to detect multiple keys being pressed WITHOUT the legacy approach. The event parameter in onKeyEvent is not RawKeyEvent type, therefore isKeyPressed() is not available there. The only thing available is event.logicalKey.keyLabel which can't be used for multiple key detection.

Upvotes: 4

Views: 2456

Answers (2)

Donny Rozendal
Donny Rozendal

Reputation: 1054

The behavior of onKeyEvent is indeed quite strange because it doesn't allow to check for modifier keys while pressing another key. It just supports handling of one key at a time. So if you want to check for multiple keys pressed, you can use HardwareKeyboard to check for another key when pressing enter. Like this:

FocusNode(
  onKeyEvent: (node, event) {
    final enterPressedWithShift = event is KeyDownEvent &&
        event.physicalKey == PhysicalKeyboardKey.enter &&
        HardwareKeyboard.instance.physicalKeysPressed.any(
          (key) => <PhysicalKeyboardKey>{
            PhysicalKeyboardKey.shiftLeft,
            PhysicalKeyboardKey.shiftRight,
          }.contains(key),
        );

    if (enterPressedWithShift) {
      // Do something
      return KeyEventResult.handled;
    } else {
      return KeyEventResult.ignored;
    }
  },
);

Upvotes: 2

powerman23rus
powerman23rus

Reputation: 1583

To handle the shortcuts Flutter has Shortcut widget. To start using it you have to specify:

  • Intent - describes that shortcut intent triggered
  • Action - describes action on triggered Intent

Let's create an intent class

class NewLineIntent extends Intent {
  const NewLineIntent();
}

Add it to your widget and specify the conditions:

static const newLine = SingleActivator(LogicalKeyboardKey.enter, shift: true);

Finally, build a widget:

@override
Widget build(BuildContext context) {
    return Shortcuts(
      shortcuts: const {
        newLine: NewLineIntent()
      },
      child: Actions(
        actions: {
          NewLineIntent: CallbackAction<NewLineIntent>(
            onInvoke: (NewLineIntent intent) {
              print('New line');
            },
          )
        },
        child: Focus(
          autofocus: true,
          child: ... ,
        ),
      ),
    );
  }

And when your widget will appear on the screen and you press Shift + Enter your shortcut will be triggered.

Upvotes: 4

Related Questions