How to Create Toggle Buttons in Flutter

Flutter Aug 15, 2023

Toggle buttons let users choose options by tapping buttons that can turn on and off. In this post, we will go through the process of making these toggle buttons in Flutter.

Basic Implementation

To get started, we will explore how to create toggle buttons that allow multiple buttons to be selected simultaneously. Let us have a look at the code example below:

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  List<bool> actions = [false, false, false];

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Toggle Buttons Demo'),
        ),
        body: Center(
          child: ToggleButtons(
            isSelected: actions,
            constraints: BoxConstraints(
              minWidth: 75,
              minHeight: 50,
            ),
            onPressed: (int index) =>
                setState(() => actions[index] = !actions[index]),
            children: <Widget>[
              Text('Share', style: TextStyle(fontSize: 20)),
              Text('Copy', style: TextStyle(fontSize: 20)),
              Text('Link', style: TextStyle(fontSize: 20)),
            ],
          ),
        ),
      ),
    );
  }
}

In this code snippet, we created a stateful MyApp widget. Inside the widget we defined a variable that holds a list of booleans called actions. The MyApp widget returns a MaterialApp widget with a Scaffold to load our page layout. Inside the Scaffold widget, we create our toggle buttons. To create a toggle button we use the ToggleButtons widget.

Inside the ToggleButtons widget we set four properties: isSelected, constraints, onPressed and children:

  • isSelected: This property expects a list of boolean values. In our case, we used the actions variable, which is a list of three boolean values, one for each button.
  • constraints: Inside the constraints property, we use the BoxConstraints class to define the minimum width and height of the buttons. This is not required, however, it helps with the demonstration.
  • onPressed: When any of the buttons is pressed, the onPressed callback function is called. It toggles the corresponding value in the actions list, changing the selection status of the button. To make this happen, we select the specific button using actions[index] and switch its value using !actions[index]. The ! operator switches the current boolean value to its opposite.
  • children: This property takes a list of widgets, each item in the list represents a button. In our case, we added three Text widgets.

When we build our applications you will see that we get three toggle buttons:

flutter_basic_implementation_of_toggle_buttons

Using Icons

As previously mentioned, the children property of the ToggleButtons widget takes a list of widgets. This makes the children property very flexible and we can easily switch to for example Icon widgets.

ToggleButtons(
  isSelected: actions,
  constraints: BoxConstraints(
    minWidth: 75,
    minHeight: 50,
  ),
  onPressed: (int index) =>
      setState(() => actions[index] = !actions[index]),
  children: <Widget>[
    Icon(Icons.share),
    Icon(Icons.copy),
    Icon(Icons.link),
  ],
),

In the code snippet, all we did is replacing the Text widgets with Icon widgets. When we build our application again, you will now see that we have toggle buttons with icons:

flutter_toggle_buttons_with_icons

Only toggle one button at a time

So far we were able to select multiple buttons simultaneously, but it is also possible to only allow one button to be selected at a time, let us go through the code:

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  int selectedButtonIndex = 0;
  List<Widget> buttons = [
    Icon(Icons.share),
    Icon(Icons.copy),
    Icon(Icons.link),
  ];

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Toggle Buttons Demo'),
        ),
        body: Center(
          child: ToggleButtons(
            isSelected:
            List.generate(buttons.length, (index) => index == selectedButtonIndex),
            constraints: BoxConstraints(
              minWidth: 75,
              minHeight: 50,
            ),
            onPressed: (int index) =>
                setState(() => selectedButtonIndex = index),
            children: buttons,
          ),
        ),
      ),
    );
  }
}

In this updated code snippet, we removed the actions variable and added two new variables: selectedButtonIndex and buttons. The SelectedButtonIndex hold the current index of the selected button, which by default is 0. The buttons variable is a list of our Icon widgets which were previously defined inside the children property of the ToggleButtons widget.

Speaking of the ToggleButtons widget we made three changes:

  • isSelected: The List.generate function is used to generate a list of booleans. When the provided index matches the selectedButtonIndex the boolean will be set to true otherwise, it will be false.
  • onPressed: In the onPressed property we now set the selectedButtonIndex to the index of the last clicked button.
  • children: This property is basically the same, but instead of directly defining the widgets inside the property we use the buttons variable.

After these changes, you are no longer able to select multiple buttons:

flutter_toggle_buttons_only_allowing_one_button_to_be_activated

Conclusion

In this post, we have explored toggle buttons in Flutter. We covered making buttons that can be tapped on and off to choose multiple options. We looked into changing the widgets inside these buttons for different looks. Additionally, we discovered how to adjust the toggle buttons so that only one can be picked at a time.

Tags