Loading... Search articles

Search for articles

Sorry, but we couldn't find any matches...

But perhaps we can interest you in one of our more popular articles?
Flutter widgets cheat sheet

Flutter widgets cheat sheet

Oct 20, 2022

This post is written by Godwin Alexander Ekainu

Flutter is an open-source tool designed to build fast and beautiful applications across multiple platforms. The Flutter SDK has been widely adopted for developing mobile applications, and many developers are learning Flutter every day. It is important to create content that can help them do this, and that’s the aim of this blog post! So, we’ve prepared a simple cheat sheet of different Flutter widgets (and in Flutter, everything is a widget!), which you can use to build your Flutter apps.

We’ve grouped the widgets into several categories:

  1. Interaction widgets. These help make your Flutter app interactive.
  2. Input widgets. These widgets are used to handle user input.
  3. Alignment and layout widgets. You use these widgets everywhere to position other widgets on the screen relative to one another and organize them into structures.
  4. Scrollable widgets. These widgets come in handy when you need to create scrollable lists and galleries.
  5. Structure widgets. These are the foundational widgets for your app.
  6. Paint widgets. These widgets allow you to customize the design of your app.
  7. Button widgets. These are, as you might have guessed, for creating buttons.
  8. Basic navigation. To navigate between screens, you’ll need navigation. We’ll provide a basic example of navigation in this article.

If you don’t understand the concept of widgets, you can refer to our Flutter From Scratch video on this topic.

How do you use this Flutter widgets cheat sheet? Just copy-paste the code for the widgets you want to use in your app, and modify it to incorporate the logic you need. Let’s get started!

1. Interaction widgets

Interaction widgets make your application dynamic and provide a good user experience, so it’s essential to understand how to use them.

GestureDetector

GestureDetector is a widget that responds to events or gestures that correspond to its non-callbacks.

  • onTap
  • onTapUp
  • onTapDown
  • onLongPress
  • onDoubleTap
  • onHorizontalDragStart
  • onVerticalDragDown
  • onPanDown
  • onScaleStart

You can use this gesture detector to create custom buttons or clickable text or pictures.

To add a gesture detector, use the code below:

    GestureDetector(
    
      onTap: () {
        const snackBar = SnackBar(content: Text('Tap'));
    
        ScaffoldMessenger.of(context).showSnackBar(snackBar);
      },
      // The custom button
      child: Container(
        padding: const EdgeInsets.all(12.0),
        decoration: BoxDecoration(
          color: Colors.lightBlue,
          borderRadius: BorderRadius.circular(8.0),
        ),
        child: const Text('My Button'),
      ),
    )

AlertDialog

The AlertDialog widget creates a window to display crucial information with options that allow the user to make decisions.

To add an alert dialog to your app, you can use the following code:

     Future<void> _showMyDialog() async {
      return showDialog<void>(
        context: context,
        barrierDismissible: false, // user must tap button!
        builder: (BuildContext context) {
          return AlertDialog(
            title: const Text('Cheat Sheet'),
            content: SingleChildScrollView(
              child: ListBody(
                children: const <Widget>[
                  Text('This is a demo alert dialog.'),
                  Text('Would you like to approve of this message?'),
                ],
              ),
            ),
            actions: <Widget>[
              TextButton(
                child: const Text('Approve'),
                onPressed: () {
                  Navigator.of(context).pop();
                },
              ),
            ],
          );
        },
      );
    }

SnackBar

The SnackBar widget is used to briefly tell a user that an action has taken place. For example, you can delete an item that triggers a snackbar, which tells the user that an item has just been deleted.

To add a snackbar to your application, use the code below:

    Center(
            child: ElevatedButton(
              onPressed: () {
              final snackBar =  SnackBar(
                content: const Text('Yay! A SnackBar!'),
                action: SnackBarAction(
                  label: 'Undo',
                  onPressed: () {
                   Text('data');
                  },
                ),
              );
                  ScaffoldMessenger.of(context).showSnackBar(snackBar);
              },
              child: const Text('Show snackbar'),
            ),
          ),

Dismissible

You can use a Dismissible widget to remove or dismiss items from a list. You can swipe left or right to remove any item.

Use the code below to implement this feature:

    List<String> items = <String>[
        'banana',
        'strawberry',
        'apple'
        'orange'
        'cat'
        'bobcat'
      ];
    ListView.builder(
              itemCount: items.length,
              padding: const EdgeInsets.symmetric(vertical: 16),
              itemBuilder: (BuildContext context, index) {
                return Dismissible(
                  background: Container(
                    color: Colors.green,
                  ),
                  key: Key(items[index]),
                  onDismissed: (DismissDirection direction) {
                    setState(() {
                      items.removeAt(index);
                    });
                  },
                  child: ListTile(
                    title: Text(
                      'Item ${items[index]}',
                    ),
                  ),
                );
              },
            ),

InteractiveViewer

If you have a big picture that doesn’t fit on the screen, you can use the InteractiveViewer widget to enable it to fit on the screen by allowing the user to zoom in and out of the picture.

    InteractiveViewer(
            boundaryMargin: const EdgeInsets.all(20.0),
            child: Container(
              decoration: const BoxDecoration(
                gradient: LinearGradient(
                  begin: Alignment.topCenter,
                  end: Alignment.bottomCenter,
                  colors: <Color>[Colors.blue, Colors.yellow],
                  stops: <double>[0.0, 1.0],
                ),
              ),
            ),
          ),

2. Input widgets

Input widgets are a very important part of modern-day Flutter applications. For example, they are used to create an account, log in, or even perform a simple search.

Flutter forms

You can create a login and signup form using these widgets.

Try creating a form using the Forms widget and TextFormFields widget:

      class MyApp extends StatelessWidget {
      const MyApp({Key? key}) : super(key: key);
      @override
      Widget build(BuildContext context) {
        const appTitle = 'Flutter Form Demo';
        return MaterialApp(
          title: appTitle,
          home: Scaffold(
            appBar: AppBar(
              title: const Text(appTitle),
            ),
            body: const MyCustomForm(),
          ),
        );
      }
    }
    // Create a Form widget
    class MyCustomForm extends StatefulWidget {
      const MyCustomForm({Key? key}) : super(key: key);
      @override
      MyCustomFormState createState() {
        return MyCustomFormState();
      }
    }
    class MyCustomFormState extends State<MyCustomForm> {
      final formKey = GlobalKey<FormState>();
      @override
      Widget build(BuildContext context) {
        // Build a Form widget using the formKey created above
        return Form(
          key: formKey,
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: <Widget>[
              TextFormField(
                decoration: const InputDecoration(
                  icon:  Icon(Icons.person),
                  hintText: 'Enter your name',
                  labelText: 'Name',
                ),
              ),
              TextFormField(
                decoration: const InputDecoration(
                  icon: Icon(Icons.calendar_today),
                  hintText: 'Enter your date of birth',
                  labelText: 'Dob',
                ),
              ),
              const ElevatedButton(
                child:  Text('Submit'),
                onPressed: null,
              ),
            ],
          ),
        );
      }
    }

Autocomplete

This widget can come in handy in search boxes.

To add autocomplete to your Flutter application, you can use the following code snippet. The options to be displayed are determined by the optionsBuilder and rendered by the optionsViewBuilder.

    // have a list of words or names from a remote source or package
    const List<String> _kOptions = <String>[
        'aardvark',
        'bobcat',
        'chameleon',
      ];
    // use the Autocomplete widget to make selections 
    Autocomplete<String>(
          optionsBuilder: (TextEditingValue textEditingValue) {
            if (textEditingValue.text == '') {
              return const Iterable<String>.empty();
            }
            return _kOptions.where((String option) {
              return option.contains(textEditingValue.text.toLowerCase());
            });
          },
          onSelected: (String selection) {
            debugPrint('You just selected $selection');
          },
        );

TextField

TextField is one of the most fundamental and commonly used widgets for keyboard input.

    TextField(
      obscureText: true,
      decoration: InputDecoration(
        border: OutlineInputBorder(),
        labelText: 'Password',
      ),
    )

3. Alignment and layout widgets cheat sheet

These widgets are very important for building UIs in Flutter.

Center

This widget centers a child within itself.

    Center( child: Text('Center me'))

Expanded

The Expanded widget expands the child of a Row or Column to fill any available space.

For example, you can use it to build a UI that fills the screen with just three containers or pictures. Theoretically, we can just specify their heights, but remember that there are different screen sizes for different devices, including tablets such as iPad devices. The expanded widget can help you create a more responsive design that can easily fit all screen sizes.

    Row(
              children: <Widget>[
                Expanded(
                  flex: 2,
                  child: Container(
                    color: Colors.amber,
                    height: 100,
                  ),
                ),
                Container(
                  color: Colors.blue,
                  height: 100,
                  width: 50,
                ),
                Expanded(
                  child: Container(
                    color: Colors.amber,
                    height: 100,
                  ),
                ),
              ],
            ),

Align

The Align widget aligns its child within itself. This widget is very flexible and can take the size of its child.

The child can be placed at different points within its parent widget using the alignment property, as shown below:

    Container(
        height: 120.0,
        width: 120.0,
        color: Colors.blue[50],
        child: const Align(
          alignment: Alignment.topRight,
          child: FlutterLogo(
            size: 60,
          ),
        ),
      ),

Row

The Row widget takes a list of widgets and arranges them horizontally. You will likely use this widget a lot when making layouts in your code.

    Row(
            children: [
              ElevatedButton(
                child: const Text('Widget 1'),
                onPressed: () => Navigator.pushNamed(context, '/second'),
              ),
               ElevatedButton(
                child: const Text('Widget 2'),
                onPressed: () => Navigator.pushNamed(context, '/third'),
              ),
               ElevatedButton(
                child: const Text('Widget 3'),
                onPressed: () => Navigator.pushNamed(context, '/fourth'),
              ),
            ],
          ),

Column

The Column widget allows you to arrange a list of widgets vertically, similar to how the Row widget aligns them horizontally.

    Column(
      children: const <Widget>[
        Text('Deliver features faster'),
        Text('Craft beautiful UIs'),
        Expanded(
          child: FittedBox(
            fit: BoxFit.contain, 
            child: FlutterLogo(),
          ),
        ),
      ],
    )

SizedBox

Use SizedBox to give a specific size to its child widget or provide some white space between widgets.

    const SizedBox(
      width: 200.0,
      height: 300.0,
      child: Card(child: Text('Size me!')),
    )

BaseLine

Use the BaseLine widget to position the child widget according to the starting point of the parent widget.

    Center(
          child: Container(
                  width: 100,
                  height: 100,
                  color: Colors.green,
                  child: Baseline(
                    baseline: 50,
                    baselineType: TextBaseline.ideographic,
                    child: Container(
                      width: 50,
                      height: 50,
                      color: Colors.purple,
                    ),
                  ),
                ),
        );

LimitedBox

Use this widget to assign a default size to a list of widgets that are unconstrained.

    LimitedBox(
             maxHeight: 150,
             maxWidth: 150,
             child: Container(
             color: Colors.red,
            )
           )

Padding

Use the Padding widget to provide space around its child. The padding widget adds space around its child using the abstract EdgeInsetsGeometry class.

The padding property of the padding widget accepts the EdgeInsets object, which allows you to add different types of padding, including padding only in certain places using EdgeInsets.only or from different angles using EdgeInsets.fromLTRB.

    const Card(
      child: Padding(
        padding: EdgeInsets.all(16.0),
        child: Text('Hello World!'),
      ),
    )

4. Scrollable widgets

ListView Builder

ListView Builder is the most used scrollable widget. It displays its children in the scroll direction one after the other. For example, if you have a long list that is dynamically created, you can use Listview.builder to display it.

Use the following code to get started:

    final List<String> entries = <String>['A', 'B', 'C'];
    ListView.builder(
      padding: const EdgeInsets.all(8),
      itemCount: entries.length,
      itemBuilder: (BuildContext context, int index) {
        return Container(
          height: 50,
          color: Colors.amber[colorCodes[index]],
          child: Center(child: Text('Entry ${entries[index]}')),
        );
      }

SingleChildScrollView

The SingleChildScrollView widget will come in handy if you have a list of items that you initially didn’t intend for the user to scroll through, but the requirements change upon implementation. In this case, you can quickly wrap the parent widget with a SingleChildScrollView to make it scrollable.

    SingleChildScrollView(
          child: Column(
            mainAxisSize: MainAxisSize.min,
            mainAxisAlignment: MainAxisAlignment.spaceAround,
            children: <Widget>[
              Container(
                color:  Colors.red,
                height: 300.0,
                alignment: Alignment.center,
                child: const Text('Fixed Height Content'),
              ),
              Container(
                color: Colors.blue,
                height: 250.0,
                alignment: Alignment.center,
                child: const Text('Fixed Height Content'),
              ),
              Container(
                color: Colors.green,
                height: 250.0,
                alignment: Alignment.center,
                child: const Text('Fixed Height Content'),
              ),
              Container(
                color: Colors.purple,
                height: 250.0,
                alignment: Alignment.center,
                child: const Text('Fixed Height Content'),
              ),
            ],
          ),
        );

5. Structure widgets

These are the widgets that compose your app. In this Flutter widget cheat sheet, we will only be highlighting two of them: Scaffold and Loader.

Scaffold

Use Scaffold widgets for all your application layers.

    Scaffold(
          appBar: AppBar(),
          body: Row(
            children: [
              ElevatedButton(
                child: const Text('Widget 1'),
                onPressed: () => Navigator.pushNamed(context, '/second'),
              ),
          ),

Adding Loader

Create Loaders for your app when making an API request.

    class SomeWidget extends StatefulWidget {
      @override
      _SomeWidgetState createState() => _SomeWidgetState();
    }
    class _SomeWidgetState extends State<SomeWidget> {
      late Future future;
      @override
      void initState() {
        future = Future.delayed(const Duration(seconds: 8));
        super.initState();
      }
      @override
      Widget build(BuildContext context) {
        return FutureBuilder(
          future: future,
          builder: (context, snapshot) {
            return snapshot.connectionState == ConnectionState.done
                ? const Text('Loaded')
                : const CircularProgressIndicator();
          },
        );
      }
    }

6. Paint widgets

Painting effects can give a finished look to your app’s design.

InkWell

With the InkWell widget, you can create ink splash effects on images or custom buttons when you click on them.

    class _SomeWidgetState extends State<SomeWidget> {
      @override
      Widget build(BuildContext context) {
        Image img = Image.network(
            'https://images.unsplash.com/photo-1592194996308-7b43878e84a6?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=687&q=80');
        return Material(
          child: Ink.image(
            fit: BoxFit.fill,
            width: 300,
            height: 300,
            image: img.image,
            child: InkWell(
              onTap: () {
                print('image');
              },
              child: const Align(
                child: Padding(
                  padding: EdgeInsets.all(10.0),
                  child: Text(
                    'PUFFIN',
                    style: TextStyle(
                      fontWeight: FontWeight.w900,
                      color: Colors.white,
                    ),
                  ),
                ),
              ),
            ),
          ),
        );
      }
    }

DecoratedBox

DecoratedBox, together with BoxDecoration, helps you add more styling to your container widget.

    Container(
          decoration: const BoxDecoration(
            borderRadius: BorderRadius.all(
              Radius.circular(12),
            ),
            gradient:RadialGradient(
          center: Alignment(-0.5, -0.6),
          radius: 0.15,
          colors: <Color>[
            Color(0xFFEEEEEE),
            Color(0xFF111133),
          ],
          stops: <double>[0.9, 1.0],
        )));

ClipRect

Use ClipRect to clip the child within different shapes.

    class DecorateContainer extends StatelessWidget {
       const DecorateContainer(Key? key, this.image) : super(key: key);
     final Image image;
      @override
      Widget build(BuildContext context) {
        return ClipRect(
      child: Container(
        child: Align(
          alignment: Alignment.center,
            widthFactor: 0.4,
            heightFactor: 1.0,
            child: image
        ),
      ),
    );
      }
    }

ClipPath

With the ClipPath widget, you can give any shape to the child widget. This means you can use it to draw any shape of your choice or according to your UI requirements with less code.

     // body of your app
    ClipPath(
            child: Container(
              width: MediaQuery.of(context).size.width,
              height: 250,
              color: Colors.red,
            ),
            clipper: CustomClipPath(),
          ),
    
    // custom class
     class CustomClipPath extends CustomClipper<Path> {
      var radius=5.0;
      @override
      Path getClip(Size size) {
        Path path = Path();
        path.lineTo(size.width / 2, size.height);
        path.lineTo(size.width, 0.0);
        return path;
      }
      @override
      bool shouldReclip(CustomClipper<Path> oldClipper) => false;
    }

7. Buttons

There are many types of buttons in Flutter, so we’ll only suggest the most useful ones in this cheat sheet.

TextButton

This is a Material button with text that has no borders.

     TextButton(
                      style: TextButton.styleFrom(
                        padding: const EdgeInsets.all(16.0),
                        primary: Colors.white,
                        textStyle: const TextStyle(fontSize: 20),
                      ),
                      onPressed: () {},
                      child: const Text('Gradient'),
                    ),

ElevatedButton

ElevatedButton is a Material button that elevates when pressed. Avoid using elevated buttons on widgets that are already elevated, like dialogs.

    ElevatedButton(
                style: ElevatedButton.styleFrom(),
                onPressed: () {},
                child: const Text('Enabled'),
              ),

FloatingActionButton

Use FloatingActionButton to create a primary action on the screen.

    Scaffold(
          appBar: AppBar(
            title: const Text('Floating Action Button'),
          ),
          body: const Center(child: Text('Press the button below!')),
          floatingActionButton: FloatingActionButton(
            onPressed: () {
              // on pressed
            },
            backgroundColor: Colors.green,
            child: const Icon(Icons.navigation),
          ),
        );

8. Basic navigation

Named routing can be used for small to medium-sized projects. Alternatively, you can use the Navigator API, which provides various routing functions.

Flutter provides named routing to enable users to navigate your application:

    void main() {
      runApp(MaterialApp(
        initialRoute: '/',
        routes: {
          '/' : ((context) => const FirstScreen()),
          '/second':(context) => const SecondScreen()
        },
        home: const MyApp()));
    }
    class MyApp extends StatelessWidget {
      const MyApp({Key? key}) : super(key: key);
      @override
      Widget build(BuildContext context) {
        return Scaffold(
            appBar: AppBar(
              title: const Text('Navigation'),
            ),
            body:const FirstScreen()
          
        );
      }
    }
    
    class FirstScreen extends StatelessWidget {
      const FirstScreen({Key? key}) : super(key: key);
      @override
      Widget build(BuildContext context) {
        return Center(
          child: ElevatedButton(
            child: const Text('Go to SecondScreen'),
            onPressed: () => Navigator.pushNamed(context, '/second'),
          ),
        );
      }
    }
    // can add this in a new file
    class SecondScreen extends StatelessWidget {
      const SecondScreen({Key? key}) : super(key: key);
      
      @override
      Widget build(BuildContext context) {
        return ElevatedButton(
          child:const Text('Go back!'),
          onPressed: () => Navigator.pop(context),
        );
      }
    }

To learn more about Flutter Navigator 2.0, read this article.

Conclusion

We have created this list of Flutter widgets as a quick reference for you while you build your Flutter app. We hope you have learned something new about these widgets that can help you improve the functionality of your Flutter application.

We have an ebook that covers a list of libraries commonly used by Flutter developers, including networking, state management, and more. You can also watch our Flutter From Scratch tutorial, which goes into detail about how to use these libraries and widgets.


This article is written by Godwin Alexander Ekainu, a Nigerian-based software developer who is keen on sharing his knowledge and explaining complex topics to help other developers learn. You can find him on Twitter and LinkedIn.

Related articles

Latest articles

Show more posts