Easy Keyboard Shortcuts in Flutter Desktop Apps

Paul Mutisya
4 min readFeb 17, 2022

--

Introduction

It hit me that Flutter does not handle keyboard shortcuts well while playing around with ideas for the Flutter Puzzle Hack. I’ve created a portable solution for that problem and it seemed to be worth sharing with the community.

Flutter was focused on iOS and Android during its early development, and their input method frameworks precluded the need for shortcuts. The keyboard was usually only visible when in an active text editing field. However, in web and desktop applications, the keyboard is an integral part of the application. Most applications, from photoshop to your browser, use the keyboard to increase productivity with a set of shortcut keys. Power users rely on keyboard shortcuts to speed through productivity apps. You probably have a set of memorized shortcuts set up for you in Intellij or Visual Studio code. Editors like vi and vim rely on the keyboard completely.

This article introduces the Keymap package that implements this in the “Flutter Way”, as a widget.

It can be attached to any part of the widget tree and affects its descendants.

The widget

  • Easily adds keyboard shortcuts to any widget tree
  • Provides a clear, readable help screen
  • Handles focus, passing up unhandled key events
  • Respects application theme colors and fonts
  • Allows styling the colors and text
  • Respects users’ selected light/dark mode by default
  • Reduces boilerplate code

Features

A help screen example is shown below. It lies above the application and is brought up by pressing F1 (or any key you assign).

Note that it respects the application’s light/dark themes by default:

The help screen is displayed as an overlay, so it lies above any widgets in the application. It allows you to set the number of columns. You can also change the colors and font used to display the help, independently of your app’s theme.

The code to produce that is simple:

The Problem Defined

When building Flutter apps for the desktop, there needs to be a quick way to add keyboard shortcuts with minimal boilerplate code and display them with descriptive text to the user.

The Native Solution

It’s important to first investigate the built-in solution and identify the problems I’m attempting to solve. There is a useful article, Flutter actions and shortcuts, which shows how to use the built-in solution and the team is actively updating the framework, for example, adding the ShortcutActivator class in 2.3.

There is also an informative article by @omlondhe explaining the need and logic behind the Flutter shortcut architecture on medium.

The architecture of shortcuts in Flutter is straightforward: a widget that takes focus, optionally handles key events and passes unhandled events to its ancestors. Flutter has built-in widgets that can handle that, including Shortcuts and ShortcutManager. These classes are too complex for the most common cases. They can lead to wordy, boilerplate code, bringing in extra classes like Intents. Flutter has recognized this as overkill in most cases and has provided more concise options.

The simplest pattern, CallbackShortcuts with a SingleActivator produces the least amount of boilerplate. Here is an example, adding shortcuts to a simpler version of the famous Flutter counter app.

This shows some of the shortcomings the package addresses. The Focus widget is required and the programmer/implementor has to worry about managing focus. Most importantly, the application user has no way to know which shortcuts are available and what they do.

A Better Solution

The package tries to require as little code as possible. Adding shortcuts is as simple as inserting KeyboardWidget into your build method and adding a list of keyboard actions (keystroke, description, method to call and optional modifiers like shift or control). Let’s look at an example, using the same code as above.

As you can see, the code is very similar. The only change is the inclusion of explanatory text for every shortcut. When the code is run and F1 (the default help key) is pressed in the running application (on a desktop computer) the following ui pops up:

It allows the user to see what shortcuts are available. It’s that simple.

Adding a Visible Help Button

We often want to add a visible widget to call up the help screen. The simplest way to do this is by adding a GlobalKey associated with the state of the help screen. It’s a common Flutter paradigm. Let’s add a help button to the AppBar of the same example.

The example shows defining the KeyboardWidget with a global key, which you can use in the onPressed method of the button you create to call the KeyboardWidget state’s toggleOverlay method, which hides/shows the help screen.

A full example of this is available in the /example/with_help_button.dart file in the published package.

Criticism Welcome

The code is available in a public, open-source package. It is very pre-alpha and any part, including the API, is subject to change.

--

--