Creating Reusable Custom Widgets in Flutter

Learn how to design and create your own custom widgets in Flutter that you can use in any of your projects or share with the world. By Jonathan Sande.

Leave a rating/review
Download materials
Save for later
Share

Everything’s a widget in Flutter… so wouldn’t it be nice to know how to make your own? There are several methods to create custom widgets, but the most basic is to combine simple existing widgets into the more complex widget that you want. This is called composition.

In this tutorial, you’ll learn how to compose a custom widget that you can reuse anywhere. These are the specific skills you’ll learn how to do:

  • Design the widget’s UI
  • Build your design using existing widgets
  • Plan and implement how users interact with the widget
Note: This is a beginner tutorial, but if you are completely new to Flutter, check out Getting Started with Flutter first.

Getting Started

Download the project by clicking the Download Materials button at the top or bottom of the page.

This article uses Android Studio, but Visual Studio Code will work fine as well.

You’ll make a music-playing app called Classical. It only plays one song, but that’s OK because the song is so great you won’t ever want to listen to anything else. :]

Here’s how the app will look when you’re done:

Classical app's finished look

The audio player control at the bottom is the custom widget that you’ll make.

Open the starter project by navigating to the starter folder and clicking Get dependencies when Android Studio prompts you to do so.

The starter project already includes some code so you can finish this project in a single tutorial. If you are curious about the app architecture, check out the article State Management With Provider.

Run the app now and you’ll see this:

Classical app's starter view

It’s time to start composing your widget so your users can listen to some delightful music.

Refactoring UI Layouts

As you probably know, Flutter’s UI layout consists of a tree of widgets.

Widget tree

Each leaf in the tree is a widget. Each branch of the tree is a widget. The whole UI itself is also just a widget. That’s what composition is all about: widgets made of widgets all the way down to the smallest components.

The code for the widget tree can get pretty nested. To make your layout code more readable and maintainable, you should factor out groups of widgets into their own standalone widget classes.

Extracting Widgets

In the lib folder, open main.dart. Find the MyApp widget, which looks like this:

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      ...
        body: SafeArea(
          ...
        ),
    );
  }
}

Even though MyApp is quite simple already, you can break it down still further. This is a good opportunity to learn about refactoring and using Android Studio’s tools to extract widgets.

Put your cursor on Stack and right-click to show the context menu. Then choose Refactor ▸ Extract ▸ Extract Flutter Widget….

This is the body of Scaffold, so name it BodyWidget.

class BodyWidget extends StatelessWidget {
  const BodyWidget({
    Key key,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Stack(
      children: <Widget>[
        // ...
      ],
    );
  }
}

Android Studio automatically created a new widget from Stack and its descendant widgets. That’s it. You’re finished. Now you know how to make custom widgets in Flutter. Thanks for reading. Come again in the next tutorial for more great content from raywenderlich.com.

Just kidding. :] There’s more to this article ahead. But in all seriousness, it really is that easy to create new widgets.

You could put BodyWidget into its own file and use it in another part of this app or even another app. While this widget itself isn’t particularly interesting, the audio player widget that you’ll build next is.

While this is fine, there are a number of advantages to extracting as a widget rather than a method or function. The main advantage for the purpose of this article is that you can reuse extracted widgets.

Note: When you extracted the Flutter widget, you may have noticed another choice in the context menu called Method. This would have returned the Stack widget tree from a method within MyApp.

Types of Custom Widgets

This article focuses on the easiest way to make custom widgets: composition, or building complex widgets by combining simpler widgets. However, it’s worth mentioning a couple of other ways to make custom widgets.

If you can’t get the widget you want by combining other widgets, you can draw it on a canvas that Flutter provides. You do this using CustomPainter. Read Drawing Custom Shapes With CustomPainter in Flutter for a great example of how to do that.

If you want to go really low level, it’s also possible to make widgets the same way that the Flutter framework does it: by using RenderObjects. The best way to learn about this is to explore the Flutter source code of a widget similar to the one you want to make. Check out Flutter Text Rendering for a real-life example of making a widget from scratch.

It’s time to get down to work. This article will take you step-by-step through everything you need to do to create your own custom widgets. Here are the steps you’ll take:

  1. Design your widget
  2. Decompose the design
  3. Build the basic widget
  4. Customize the look
  5. Determine the user interaction
  6. Define the parameters
  7. Implement the parameters
  8. Test the widget
  9. Share your widget with the world

In the next four steps, you’ll determine how the user interface will look.

Designing Your Widget

It’s helpful to have a visual representation of the widget you want in your mind. Sketch it out on paper or use design software to draw it.

You can also borrow design ideas from others. Just because you’re a developer, doesn’t mean you can’t learn to be a great designer as well. If you’re into podcasts, check out Design Advice for Engineers to further develop your skills in this area.

For an audio player control widget, MediaElement.js is a good solid place to start:

MediaElement.js Audio Player's UI design showing a play button, the current time, a time slider, the total time and volume control

The volume control is not important for this tutorial, so crop it out:

MediaElement.js without volume control

Decomposing the Design

Once you have the design you want, identify which smaller widgets you can use to build it. You should be able to get something close with IconButton, Slider, Container and a couple of Text widgets.

Audio player decomposed into widgets

Oh, yes, they’re laid out in a row, so you’ll need a Row widget, too.