Flutter UIWhat is Flutter?
An Introduction and Overview

Ever since the Flutter 2.0 announcement, Flutter has been getting a lot of hype and publicity. If you've already been developing with Flutter, then you probably understand where this hype is coming from. If you're new to Flutter, then I highly suggest you look into it.

There is a reason developers love this thing.

So, what is Flutter?

Pulling from Flutter's homepage,

Flutter is Google’s UI toolkit for building beautiful, natively compiled applications for mobile, web, and desktop from a single codebase.

The root of this message is that Flutter is a UI toolkit. A damn good one at that. Its purpose is to make creating beautiful UI easier.

With the combination of Flutter as the UI toolkit and Dart as the engine that drives it, the result is a powerful framework to write cross-platform apps with.

What are Widgets?

First rule,

Everything is a widget

In Flutter, everything is a Widget, and part of the joy of working with Flutter is utilizing its built-in widgets. There are tons of them and they are generally easy to understand, use, and add style to.

You can either have a StatelessWidget or a StatefulWidget.

As the name implies, Stateless Widgets do not hold a state. Once they are constructed, that is it.

Stateful Widgets on the other hand, can have a state. Any updates to the state causes that widget to be refreshed in the widget tree therefore updating what appears on the screen.

We won't get into the management of state for a widget in this introduction, but it is an important topic and I encourage you to learn more about it. If you're looking for resources, here is a great video by Tadas Petra on the topic.

Here are the absolute need to know widgets when getting into Flutter development.

On top of these basic widgets, I suggest you browse through the Widget of the Week Playlist created by the Flutter team themselves. This playlist contains the basics along with some fun and less commonly used widgets that might surprise you. Each video is short and digestable and should be enough to get you started with that Widget.

Like mentioned before, everything is a Widget. Even the custom UI that you write for your own applications are Widgets.

This is one of the simplest widgets Flutter has. A simple Text widget that displays whatever string you pass it.

Text("Hello World")

If we want to create our own custom widget involving Text, we create a widget that is composed of Text. Flutter prefers composition over inheritance

It looks something like this.

class MyCustomWidget extends StatelessWidget {
    @override
    Widget build(BuildContext context) {
      return Container(
        color: Colors.red,
        child: Text("Hello World"),
      );
    }
  }

Notice that Text is a child of the Container, therefore our custom widget is composed of both a Container and Text.

On the screen, that code translates to look something like this. The Container gives the background a red color and the Text displays the string.

Composed Example

Super simple! If we add some basic styling, we can make a widget that can be reused throughout our app.

class SupremeLogo extends StatelessWidget {
    @override
    Widget build(BuildContext context) {
      return Container(
        color: Colors.red,
        padding: EdgeInsets.all(4),
        child: Text(
          "Supreme",
          style: TextStyle(
            fontSize: 24,
            fontWeight: FontWeight.bold,
            fontStyle: FontStyle.italic,
            color: Colors.white,
          ),
        ),
      );
    }
  }

And it looks like this!

Supreme Example

Congrats, we have made the Supreme logo with just a few lines of code 🎉

To reuse this widget, we can just compose again and call the constructor for our custom widget, SupremeLogo. Let's add a column full of these logos.

class ManySupremeLogos extends StatelessWidget {
    final List<SupremeLogo> supremeLogos =
        List<SupremeLogo>.generate(8, (_) => SupremeLogo());
  
    @override
    Widget build(BuildContext context) {
      return Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: supremeLogos,
      );
    }
  }

We now have a new custom widget called ManySupremeLogos that is composed of a Column and our other custom widget, SupremeLogo. Here is what that looks like.

Many Supreme Logos

It's ✨ beautiful ✨, a column of Supreme logos.

We could keep taking this further and create many more custom widgets that compose each other, but I think you get the idea.

Widgets and Screens and Apps, oh my

Using the composition mentality, it can be quite easy to break an entire Flutter app down into parts.

  1. The app itself
  2. The screens that make up the app
  3. The widgets that make up the screens

In other words,

An app is composed of screens that are composed of widgets.

We already took a look at widgets, the building blocks of any Flutter app, so let's look at Screens next.

Screens

A Screen is what takes up the entire viewing space at any point in an app.

Screens can be navigated to, navigated from and almost always begin with the same widget each time. This Widget is the Scaffold widget.

In our previous Supreme example, this is actually what the code for the entire Screen looks like.

class MyScreen extends StatelessWidget {
    @override
    Widget build(BuildContext context) {
      return Scaffold(
        body: Center(
          child: ManySupremeLogos(),
        ),
      );
    }
  }

Notice that it is also a Widget. (composed of a Scaffold and Center and ManySupremeLogos, yada yada yada. Last one I swear, you get the idea)

The Scaffold here gives us a structure to work with for the Screen at hand and allows us to add typical UI elements found within an app. For example, an AppBar! Let's add one now.

class MyScreen extends StatelessWidget {
    @override
    Widget build(BuildContext context) {
      return Scaffold(
        appBar: AppBar(
          title: Text("Supreme Screen!"),
          centerTitle: true,
        ),
        body: Center(
          child: ManySupremeLogos(),
        ),
      );
    }
  }

Easy! The screen looks like this now.

Supreme Screen

Simple enough. Let's look at how Apps are structured now.

Apps

Once again, everything in Flutter is a widget. The starting point of an App is no exception. Here is the code for the starting point of our Supreme app

void main() {
    runApp(MyApp());
  }
  
  class MyApp extends StatelessWidget {
    @override
    Widget build(BuildContext context) {
      return MaterialApp(
        debugShowCheckedModeBanner:
            false, // i.e. Hide debug banner
        home: MyScreen(),
      );
    }
  }

main() is the actual starting point of the app. It is called when you first run flutter run

It then runs the app using the Widget passed to it. In this case, MyApp.

Notice, MyApp contains a widget called MaterialApp. Similar to a Scaffold with Screens, an application needs one of these at the beginning of its lifecycle.

It is essentially a wrapper that allows for all sorts of functionality: default theme, navigation, metadata, etc.

For example, let's make our App use a dark theme. We can set that inside of the MaterialApp.

void main(){
    runApp(MyApp());
  }
  
  class MyApp extends StatelessWidget {
    @override
    Widget build(BuildContext context) {
      return MaterialApp(
        debugShowCheckedModeBanner: false, // i.e. Hide debug banner
        theme: ThemeData.dark(),
        home: MyScreen(),
      );
    }
  }

Now, with such a simple change, our entire application is rethemed!

Dark Theme App

Awesome 😎

Conclusion

  • Flutter is great
  • Something, something composition
  • Widgets, Screens, Apps

Hope you enjoyed the read!

Cheers,

- Zach