shawn.blais

Shawn has worked as programmer and product designer for over 20 years, shipping several games on Steam and Playstation and dozens of apps on mobile. He has extensive programming experience with Dart, C#, ActionScript, SQL, PHP and Javascript and a deep proficiency with motion graphics and UX design. Shawn is currently the Technical Director for gskinner.

@tree_fortress

Flutter: Accelerate your testing with Keyboard listeners

Often when working on a new library or widget, you would like to wire up many temporary testing hooks during development.

Usually in Flutter you would create some buttons, and assign some handlers to trigger all the actions you need. The problem with this is the boilerplate and time required to constantly be writing UI. It takes time, and can clutter up your example code substantially, not to mention the on-screen clutter that half a dozen tappable areas introduces.

Coming from a Unity background, (and also Flash), we were accustomed to using keyboard listeners to quickly test things; only building UI when we actually want to see it. It turns out this is quite easy! Just run on one of the desktop targets and use RawKeyboard.instance.addListener and listen for the keys you are interested in.

Lets say you are working on a pageRouter, and you just want to quickly test a variety of links to make sure everything is routing properly. You can just add your listener inside of a StatefulWidget:

  void initState() {
    super.initState();
    RawKeyboard.instance.addListener(_handleKeyDown);
  }

  void _handleKeyDown(RawKeyEvent value) {
      if(kReleaseMode) return; // Don't let these hooks slip into release!
    if (value is RawKeyDownEvent) {
      final k = value.logicalKey;
      if (k == LogicalKeyboardKey.digit1) 
         setState(() => currentPath = "/home");
      if (k == LogicalKeyboardKey.digit2) 
         setState(() => currentPath = "/settings/");
      if (k == LogicalKeyboardKey.digit3) 
         setState(() => currentPath = "/settings/alerts");
      if (k == LogicalKeyboardKey.digit4) 
         setState(() => currentPath = "/settings/profile");
      if (k == LogicalKeyboardKey.digit5) 
         setState(() => currentPath = "/settings/billing");
      ... etc
    }
  }

And you should also clean them up in dispose() otherwise your listener will outlive your view:

@override
  void dispose() {
    RawKeyboard.instance.removeListener(_handleKeyDown);
    super.dispose();
  }

Word of Caution

It’s important to note this is a global key handler, it does not know whether you are typing in a textfield somewhere else, or even if this view is visible/focused. If you do use this for shortcuts in production, you must make sure to handle these edge cases yourself. Generally using a RawKeyboardListener or Shortcuts widget is recommended since they will do this for you.

With that said, there are certainly some cases where you might want an app-wide shortcut, or maybe to trigger shortcuts for Widgets that are not currently focused, and in those cases RawKeyboard is a great option.

Flokk – How we built a Desktop App Using Flutter

Earlier this year Google and Ubuntu approached us with an open brief, to try and create a full-scale desktop application for Linux, macOS, Web, and Windows. The result was Flokk, which we released (and open-sourced) back in July.

In this post, we’re going to dive into some of the challenges we faced, the discoveries we made, and desktop-specific features that we added.

Continue reading →

Flutter: Introducing StatsFl, an FPS monitor for Flutter

As we begin pushing Flutter to more platforms such as Desktop and Web, it is becoming increasingly important to quickly and easily measure performance of your application. While the built-in performance monitor gets the job done, it leaves a lot to be desired in terms of readability and flexibility.

As the old school Flash devs we are, we remember the days when virtually every Flash application around would use the hi-res-stats package by mrdoob (yes, that mrdoob). It was extremely helpful to catch performance issues, and make sure your application was smooth (which in those days, was a solid 24fps!).

Currently nothing like that exists in the Flutter community. To help fill this gap, we’ve created StatsFl! Available now on pub.dev: https://pub.dev/packages/statsfl

Continue reading →

Flutter: Simplify Platform & Screen Size Detection

In the never-ending quest to reduce boilerplate and DRY up our code in Flutter, we have noticed that using the MediaQuery class can be a bit cumbersome, and it’s also missing a couple of key pieces of information.

The issues we see are:

  • MediaQuery.of(context) is a bit verbose on its face
  • Checking for orientation especially is too long:
    bool isLandscape = MediaQuery.of(context).orientation == Orientation.landscape
  • There is no diagonal size parameter, so you can’t easily get the true screen size of the device, helpful for determining your form factor
  • There is no way to get the size in inches, which can be useful when thinking about breakpoints (for most people, 4.5″ is easier to picture, than 720 logical pixels)

To that end, we have small Screen helper class, that we use across all our new projects:

Continue reading →

Google, Adobe, gskinner | Flutter Interact ’19

Flutter is a mobile UI toolkit that combines fast development, expressive and beautiful UIs, with native performance. To test-drive the platform, Grant Skinner & Mike Chambers recently built Redrix: a mobile companion app for Destiny 2.

Download Redrix on iOS or Android
Continue reading →