Visual Programming with Flutter

James Williams
Jul 15 · 4 min read

A couple months ago when re-immersing myself in Flutter, I thought, “I really like Flutter but its declarative nature sometimes gets me confused on what Widgets go where, I wonder if there’s a way to make it less confusing.” I come from a teaching background so it seemed ripe for an experimental learning project to code without code.

AppInventor piqued my interest a bit, until I saw it uses a totally non-standard library for its code and interactions. Even though it’s an experiment, I wanted it to be grounded in code that would appear in a typical Flutter app. Looking into AppInventor did clue me in to Blockly, a library to generate code with interlocking building blocks.

Blockly is used in a lot of educational and hobbyist environments like Scratch, micro:bit, and even some Arduino applications.

Google Developers:Blockly

Blockly can generate JavaScript, Python, PHP, Lua, and Dart code. Blockly is extensible to other languages but having it already understand Dart, albeit with some needed tweaks, is a big win.

There are a number of built-in blocks for common constructs like conditional statements, loops, various numeric operations, lists, and functions. For anything beyond that, you can create your own blocks using the Blockly Developer Tools.

Blockly Developer Tools: used to create new blocks

The developer tools give you options to determine inputs/outputs and how the blocks will link with others. The generator stub is how that block will represent itself in final code.

Flutter Blockly Components

I started with a small set of Widget components initially trying to implement the inner core of a Scaffold before moving outward to encompass MaterialApp and even Stateless and Stateful widgets.
- MaterialApp
- Scaffold
- AppBar
- Row
- Column
- ListView
- Icon
- Text
- Placeholder
- FloatingActionButton / RaisedButton

The focus was less on trying to implement every single widget but to implement ENOUGH to give some customization and keep the app flow easy to read.

StatelessWidget and StatefulWidget

StatelessWidget and StatefulWidget were the first big challenge. First, they need to be classes which Blockly isn’t built to accommodate, aligning to a more functional style. Second, functions and variable declarations also default to being global. That’s great for a main function, not so much for a build(BuildContext context) or whatever needed state variables.

Building out a component to model a class wasn’t too difficult for a StatelessWidget. It’s a matter of assigning a block of widgets to the build property and extrapolate that into a proper build function.

A Stateless widget with a Column of Text widgets
The generated code for a StatelessWidget with a Column of Text widgets

StatefulWidgets were a little bit trickier. The variables need to live inside the class derived from State. Inlining variables inside a class required a minor hack: creating a new block that would take raw code input. This is a minor misuse because any Blockly doesn’t know about any variable created this way. You lose the ability to use them in larger blocks. Once raw code, always raw code.

A Stateful widget represented in Blockly blocks
The code generated from StatefulWidget and raw code blocks

Another head scratcher was setState. Naturally I created a block for it but if you put that block in a function, it defaults to global and you’d get errors that it’s not a StatefulWidget.

This was the source of hack number two. The setState block would take in raw code and be directly assignable to onPressed on buttons.

Et voilà, I was able to make a Stateful Hello World (Counter) app without a single line of code. Well technically, 3 lines of code.

Here’s start to finish in a video (no audio). Empty MaterialÀpp and Scaffold instances have been created and flutter run has been started and is pointing Flutter project that will receive updates from the web app. A similar flow is possible with Flutter Web however some widgets don’t map 1:1 from mobile to web.

And here’s how the finished app looks in blocks:

You can try it out online or check out the code from Github.

Note: The cloud download button will download the main.dart file to your computer. The Dart tab needs to be active or the saved file will be empty.

Special thanks to Lara Martín for being a sounding board to verify the idea wasn’t totally odd and to Nate Ebel for proofing this post and giving feedback.

James Williams

Written by

Android Certification SWE, Advanced Systems Group at Google, Fmr Android Lead @Udacity

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade