Essential Flutter Widgets for Your Apps

Jun 15, 2024

This article is part of the series:

Flutter is a mobile app development framework created by Google that has gained popularity for its ability to build high-quality applications with a single codebase. We have already discussed this in depth here. We have also seen that one of the fundamental pillars of Flutter is its focus on Widgets. In Flutter, everything is a widget. From the simplest text to complex user interfaces, everything is built using Widgets. This greatly simplifies development and provides flexibility for developers. If you are just starting with Flutter, I recommend reading the previous chapters of the series before continuing.

A widget in Flutter is a UI component that describes a part of the interface. They form the basis of an application and can be of different types, such as buttons, texts, images, lists, among others. These not only define the structure and appearance of the interface but also how it behaves and reacts to user interaction.

We have already seen that by default, Flutter distinguishes between two types of widgets: StatelessWidget and StatefulWidget. Now we are going to delve into some of the most common and useful widgets used in Flutter application development to shape and structure our user interface.

In addition to StatelessWidget and StatefulWidget, Flutter provides a wide range of built-in widgets that cover almost all the needs of mobile application development. These can be classified into various categories.

Types of Widgets

Layout Widgets

Layout widgets are responsible for organizing and positioning widgets on the screen. Some of the layout widgets along with their most common parameters are:

  • Row: Organizes its children in a horizontal row.

    • children: List of widgets to be displayed in the row.
    • mainAxisAlignment: Main alignment of the children.
    • crossAxisAlignment: Cross alignment of the children.
    • mainAxisSize: Defines whether the main axis occupies the minimum or maximum size.
  • Column: Organizes its children in a vertical column.

    • children: List of widgets to be displayed in the column.
    • mainAxisAlignment: Main alignment of the children.
    • crossAxisAlignment: Cross alignment of the children.
    • mainAxisSize: Defines whether the main axis occupies the minimum or maximum size.
  • Container: Allows customization of its children’s appearance, such as background color, margin, padding, etc.

    • alignment: Alignment of the content within the container.
    • padding: Internal padding of the container.
    • margin: External margin of the container.
    • decoration: Decoration of the container, such as borders and shadows.
    • width: Width of the container.
    • height: Height of the container.
  • Padding: Adds padding to its children.

    • padding: Defines the padding around the child.
    • child: Child widget that receives the padding.
  • Center: Centers its children on the screen.

    • child: Child widget to be centered.
  • Expanded: Expands its child to fill the available space.

    • child: Child widget to be expanded.
    • flex: Flex factor that determines the amount of additional space assigned.
  • SizedBox: A container that imposes a fixed size on its children.

    • width: Width of the SizedBox.
    • height: Height of the SizedBox.
    • child: Child widget that receives the fixed size.
  • ListView: Displays a scrollable list of elements.

    • children: List of widgets to be displayed in the list.
    • padding: Padding around the list elements.
  • GridView: Displays a grid of elements.

    • children: List of widgets to be displayed in the grid.
    • padding: Padding around the grid elements.
  • Stack: Stacks its children on top of each other.

    • children: List of widgets to be stacked.
    • alignment: Alignment of the children within the stack.
    • fit: How to size the children within the stack.
  • Align: Aligns its child within itself.

    • alignment: Alignment of the child within the widget.
    • child: Child widget to be aligned.
    • widthFactor: Width adjustment factor.
    • heightFactor: Height adjustment factor.

Display Widgets

Display widgets are responsible for showing information on the screen. Some of the most common display widgets are:

  • Text: Displays text on the screen. The text to be displayed must be provided as the first parameter.

    • style: Text style.
    • textAlign: Text alignment.
    • maxLines: Maximum number of lines.
  • Image: Renders an image on the screen.

    • image: The image to display.
    • width: Width of the image.
    • height: Height of the image.
    • fit: How to fit the image within its container.
    • alignment: Alignment of the image.
    • color: Color to tint the image.
  • Icon: Displays an icon on the screen.

    • icon: The icon to display.
    • size: Size of the icon.
    • color: Color of the icon.
    • semanticLabel: Semantic label for accessibility.
  • Card: Presents a card with a shadow and typically rounded corners.

    • child: Child widget inside the card.
    • color: Background color of the card.
    • elevation: Elevation of the card.
    • margin: External margin of the card.
    • shape: Shape of the card.
  • Chip: Displays a label with an icon and text.

    • label: The text of the label.
    • avatar: A widget, typically an image or icon, that appears before the text.
    • deleteIcon: An icon that appears at the end of the chip.
    • onDeleted: Callback function that is executed when the chip is deleted.
    • backgroundColor: Background color of the chip.
  • Divider: Inserts a dividing line between elements.

    • color: Color of the line.
    • height: Height of the space occupied by the divider.
    • thickness: Thickness of the line.
    • indent: Space before the line.
    • endIndent: Space after the line.
  • Tooltip: Provides an informative pop-up message.

    • message: The text of the tooltip.
    • child: The widget associated with the tooltip.
    • preferBelow: Whether the tooltip should be shown below the widget.
  • SnackBar: Offers a temporary pop-up message.

    • content: Main content of the SnackBar.
    • action: An action that the user can take.
  • CircularProgressIndicator: Indicates progress with a circular indicator.

    • value: Current progress (0.0 to 1.0).
    • backgroundColor: Background color of the circle.
    • valueColor: Color of the progress.
    • strokeWidth: Thickness of the circle line.
  • LinearProgressIndicator: Represents progress linearly.

    • value: Current progress (0.0 to 1.0).
    • backgroundColor: Background color of the bar.
    • valueColor: Color of the progress.
    • minHeight: Minimum height of the bar.
  • AppBar: Provides an application bar at the top of the screen.

    • title: The main title of the AppBar.
    • actions: List of widgets displayed as actions in the AppBar.
    • leading: Widget displayed at the beginning of the AppBar.
    • backgroundColor: Background color of the AppBar.
    • elevation: Elevation of the AppBar.
  • Drawer: Displays a sliding panel from the edge of the screen.

    • child: Child widget inside the Drawer.
    • elevation: Elevation of the Drawer.
    • semanticLabel: Semantic label for accessibility.
    • backgroundColor: Background color of the Drawer.
  • Dialog: Shows a dialog box that appears above the main content.

    • child: Child widget inside the dialog.
    • backgroundColor: Background color of the dialog.
    • shape: Shape of the dialog.
  • AlertDialog: Shows a dialog box above the main content with custom actions. All AlertDialog are Dialog but not all Dialog are AlertDialog.

    • title: Title of the dialog.
    • content: Main content of the dialog.
    • actions: List of widgets representing the dialog actions.
    • backgroundColor: Background color of the dialog.
    • shape: Shape of the dialog.

Action Widgets

Action widgets are responsible for handling user interaction. Some of the most common button widgets are:

  • ElevatedButton: Presents an elevated button with a colored background.

    • onPressed: Callback that is executed when the button is pressed.
    • child: Content of the button.
    • style: Style of the button.
  • TextButton: Offers a text button without a background.

    • onPressed: Callback that is executed when the button is pressed.
    • child: Content of the button.
    • style: Style of the button.
  • IconButton: Displays a button with an icon.

    • icon: The icon to display.
    • onPressed: Callback that is executed when the button is pressed.
    • tooltip: Informative pop-up message.
    • color: Color of the icon.
    • iconSize: Size of the icon.
  • FloatingActionButton: Displays a circular floating button.

    • onPressed: Callback that is executed when the button is pressed.
    • child: Content of the button.
    • backgroundColor: Background color of the button.
  • PopupMenuButton: Displays a pop-up menu.

    • itemBuilder: Function that creates the menu items.
    • onSelected: Callback that is executed when an item is selected.
    • icon: Icon of the button.
    • initialValue: Initially selected value.
  • DropdownButton: Presents a drop-down menu.

    • items: List of menu items.
    • onChanged: Callback that is executed when an item is selected.
    • value: Currently selected value.
    • hint: Widget that is displayed when no value is selected.
  • OutlinedButton: Offers a button with a border but no background.

    • onPressed: Callback that is executed when the button is pressed.
    • child: Content of the button.
    • style: Style of the button.

Input Widgets

Input widgets are responsible for collecting information from the user. Some of the most common input widgets are:

  • TextField: Allows the user to enter text.

    • controller: Controller for the text field.
    • decoration: Decoration for the text field.
    • keyboardType: Type of keyboard to display.
    • obscureText: Whether the text should be hidden (e.g., for passwords).
    • onChanged: Callback that is executed when the text changes.
    • validator: Validation function for the field.
  • Slider: Displays a sliding control.

    • value: Current value of the slider.
    • onChanged: Callback that is executed when the value changes.
    • min: Minimum value.
    • max: Maximum value.
    • divisions: Number of divisions.
  • Checkbox: Presents a checkbox.

    • value: Whether the checkbox is checked.
    • onChanged: Callback that is executed when the value changes.
    • activeColor: Color of the checkbox when it is checked.
    • checkColor: Color of the checkmark.
    • tristate: Whether the checkbox allows a third state (null).
  • Switch: Displays an on/off switch.

    • value: Whether the switch is on.
    • onChanged: Callback that is executed when the value changes.
    • activeColor: Color of the switch when it is on.
    • activeTrackColor: Color of the track when it is on.
    • inactiveThumbColor: Color of the switch when it is off.
  • Radio: Provides a radio button.

    • value: Value of the radio button.
    • groupValue: Value of the group of radio buttons.
    • onChanged: Callback that is executed when the value changes.
    • activeColor: Color of the radio button when it is selected.
    • toggleable: Whether the radio button is toggleable.
  • Form: Groups multiple input fields and provides validation.

    • child: Child widget within the form.
    • key: Key for the form.
    • autovalidateMode: Autovalidation mode for the form.
    • onChanged: Callback that is executed when any field in the form changes.
    • onWillPop: Callback that is executed when attempting to close the form.

Thanks to all these Widgets and the flexibility provided by Flutter, we can easily build complex and attractive user interfaces for mobile applications with exceptional appearance and functionality. There are many more and they can even be extended with custom widgets created by yourself or by the community. By using just a few of the widgets listed here, you can create something similar to what is shown in the following screenshot. If you want to see the source code, keep reading.

Practical Example

For our example, we are going to combine some of these widgets to build an attractive and functional user interface. In it, we will see several of the different types of widgets we have mentioned so far, such as the Drawer:


    Drawer(
        child: SizedBox(
          height: double.infinity,
          width: 200,
          child: ListView(
            padding: EdgeInsets.zero,
            children: <Widget>[
              DrawerHeader(
                decoration: BoxDecoration(
                  color: Theme.of(context).primaryColor,
                ),
                child: Text(
                  'Drawer Header',
                  style: TextStyle(
                    color: Colors.white,
                    fontSize: 24,
                  ),
                ),
              ),
              ListTile(
                leading: Icon(Icons.home),
                title: Text('Home'),
                onTap: () {
                  Navigator.pop(context);
                  ScaffoldMessenger.of(context).showSnackBar(
                    SnackBar(
                      content: Text('Home tapped'),
                    ),
                  );
                },
              ),
              ListTile(
                leading: Icon(Icons.settings),
                title: Text('Settings'),
                onTap: () {
                  Navigator.pop(context);
                  ScaffoldMessenger.of(context).showSnackBar(
                    SnackBar(
                      content: Text('Settings tapped'),
                    ),
                  );
                },
              ),
            ],
          ),
        )
      )
    

In this example, we have used the Drawer widget to display a sliding panel with two items: Home and Settings, as a typical side menu in many mobile applications. When selecting one of the items, a SnackBar with an informative message is shown in our case, but we could navigate to another screen or perform any other action.

Another noteworthy widget is the FloatingActionButton that appears in the bottom right corner of the screen. This circular floating button is very common in mobile applications and is used for prominent or common actions. In our case, we simply display a dialog when it is pressed:


    FloatingActionButton(
        onPressed: () {
          showDialog(
            context: context,
            builder: (context) {
              return AlertDialog(
                title: Text('Alert Dialog'),
                content: Text('This is an alert dialog where you can cancel or confirm.'),
                actions: [
                  TextButton(
                    onPressed: () {
                      Navigator.pop(context);
                    },
                    child: Text('Cancel'),
                  ),
                  TextButton(
                    onPressed: () {
                      Navigator.pop(context);
                      ScaffoldMessenger.of(context).showSnackBar(
                        SnackBar(
                          content: Text('You are now a new member of the club!'),
                        ),
                      );
                    },
                    child: Text('Confirm'),
                  ),
                ],
              );
            },
          );
        },
        child: Icon(Icons.info),
      )
      

In the previous example, we see the combination of two widgets to display a dialog with two action buttons after pressing the floating button. For our example, everything is in the same place, but it might be advisable to modularize the code and separate the different elements into different places to maintain a clean and organized structure.

The bottom navigation widget BottomNavigationBar is another common widget in mobile applications. In this case, we have used a BottomNavigationBar with three items: Home, Search, and Profile. When one of the items is selected, the application navigates to a different window, similar to a tab layout but at the bottom of the screen:


    BottomNavigationBar(
        currentIndex: _selectedIndex,
        onTap: _onItemTapped,
        items: const <BottomNavigationBarItem>[
          BottomNavigationBarItem(
            icon: Icon(Icons.home),
            label: 'Home',
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.search),
            label: 'Search',
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.person),
            label: 'Profile',
          ),
        ],
      )
      

The interactive widgets included in the sample application, such as the Switch, Slider, and Checkbox, are also quite common elements in mobile applications and are used to collect user information. In our source code, each of them is encapsulated in a Card widget to give them a more attractive and organized appearance. The volume control additionally displays the information differently compared to the other two to make the user experience friendlier. While the Switch and Checkbox only have two possible states (on/off), the Slider allows multiple decimal values between 0 and 1, so it wouldn’t make sense to show a Snackbar every time it changes:


    Card(
        child: Padding(
          padding: const EdgeInsets.all(8.0),
          child: Row(
            children: [
              Text('Enable Notifications', style: TextStyle(fontSize: 18)),
              Spacer(),
              Switch(
                value: _isNotificationEnabled,
                onChanged: (bool value) {
                  setState(() {
                    _isNotificationEnabled = value;
                  });
                  ScaffoldMessenger.of(context).showSnackBar(
                    SnackBar(
                      content: Text('Notifications ${value ? 'enabled' : 'disabled'}'),
                    ),
                  );
                },
              ),
            ],
          ),
        ),
      ),
      Card(
        child: Padding(
          padding: const EdgeInsets.all(8.0),
          child: Row(
            children: [
              Text('Dark Mode', style: TextStyle(fontSize: 18)),
              Spacer(),
              Checkbox(
                value: _isDarkModeEnabled,
                onChanged: (bool? value) {
                  setState(() {
                    _isDarkModeEnabled = value ?? false;
                  });
                  ScaffoldMessenger.of(context).showSnackBar(
                      SnackBar(
                        content: Text('Dark Mode ${value ?? false ? 'enabled' : 'disabled'}'),
                      )
                  );
                },
              ),
            ],
          ),
        ),
      ),
      Card(
        child: Padding(
          padding: const EdgeInsets.all(8.0),
          child: Row(
            children: [
              Text('Volume', style: TextStyle(fontSize: 18, fontStyle: FontStyle.italic)),
              SizedBox(width: 20),
              Text(_volumeValue.toStringAsFixed(2)),
              Spacer(),
              Slider(
                value: _volumeValue,
                onChanged: (double value) {
                  setState(() {
                    _volumeValue = value;
                  });
                },
              ),
            ],
          ),
        ),
      ),
    

And that’s it for this chapter of our Flutter series. I invite you to explore for yourself how we combined some of the widgets mentioned here to shape the user interface of our application. The complete source code is available in our GitHub repository, where you can view it and download it to try it out yourself and make any modifications you see fit. You could start by adding those widgets from the list that have not been integrated into the application and familiarize yourself with those you do not know. If you enjoyed this article and want to continue learning about Flutter and other mobile app development topics, let us know what you think and what you would like to see in future articles. And above all, Happy Coding!

Related posts

That may interest you

September 15, 2023

Flutter introduction

Flutter is a mobile app development framework created by Google. It utilizes the Skia rendering …

read more