Thinking in widgets

on Friday, 24th of July, 2020

In Flutter, everything is a widget. Widgets are just tiny chunks of UI that you can combine to make a complete app. Building an app Flutter is like building a lego set -- piece by piece.

Widgets are nested inside of each other to build your app. Even the root of your app is just a widget. It's widgets all the way down.

Flutter is unique in that every aspect of UI is handled with Widgets.

A widget might display something, it might help define design, it might help with layout, or it may handle interaction. I really can't drive this home enough: everything is a widget.

  • A simple widget that displays text: const Text('Hello World').
  • A simple widget that a user interacts with const Button(onTap: ...callback...)
  • A simple widget that adds a background color: const BoxDecoration(background: Colors.blue)

If you're coming from the web: imagine that your CSS, HTML, and JavaScript are all handled by widgets. There is no markup language. There is no CSS. Just widgets.

Widget Hierarchy

In this picture, every thing that's outlined is a widget:

Outlined widgets

This picture is from one of the tutorial apps on FlutterByExample, and this is a detail page, of which there is one for every dog in the app.

The green outline represents the page. And a page in Flutter is a widget. The blue outlines represent pieces of UI that logically group together. The rest are outlined white, and they're simply dumb components that have no concern over their content, they just display what they're told.

This is the widget hierarchy for this page:

  • PageWidget
    • DogProfileWidget
      • CircleImage
      • Text
      • Text
      • Text
      • Container
        • Icon
        • Text
    • RateDogWidget
      • Slider
      • Text
      • SubmitButton
This isn't _exactly_ accurate, there are layout widgets such as `columns`and `padding` in here that I'm glossing over.

Design for Re-usability

The most important part of using Flutter Widgets effectively is designing your lowest level widgets to be reusable.

For example, the CircleImage widget from the image above:

class CircleImage extends StatelessWidget {
 final String renderUrl;

 CircleImage(this.renderUrl);

 
 Widget build(BuildContext context) {
   return new Container(
    width: 100.0,
    height: 100.0,
    decoration: new BoxDecoration(
      shape: BoxShape.circle,
      image: new DecorationImage(
        fit: BoxFit.cover,
        image: new NetworkImage(renderUrl ?? ''),
      ),
    ),
  );
 }
}

Then, anywhere in your app, you can reuse this Widget: new CircleImage('https..). This component is designed for re-usability because anywhere in your app that you may want a round image of a certain size, you can just pass in a url and there you have it. There's no need to re-write this widget over and over.

And, this circle image doesn't care at all about what it's displaying. It's just enforcing styles.

In the test app that these images are from, I also have a list of all the dogs in the app. Heres a picture of one of the cards:

Dog card

In that Widget, I don't need to rewrite the circle image, because I've already built it once.



Join thousands of Flutter developers.

Sign up for infrequent updates about Flutter and Dart.

You can get all this content and more in one place. Check out my new book Flutter in Action