This is the 10th day of my participation in Gwen Challenge

The realization of the bottom popover is introduced in a chapter about the introduction and practice of Flutter. After sending out, I was thinking about how to achieve multiple selection, which is also a very common function. This paper introduces the idea and implementation of multiple selection.

The difference between multiple selection and single selection

When selecting a radio option, you can directly return the result, so there is no state management required for the bottom popup. But when it comes to multi-selection, you need to know the current selected option, save it when it is clicked, and empty it when it is clicked again. At the same time, the interface also needs to be updated synchronously, so it involves state management.

implementation

Flutter provides a StatefulBuilder class that provides a Builder method for building stateful components and a state update method, so state management is done in Flutter.

StatefulBuilder(builder: (context1, setState) {
  	returnWidget; })Copy the code

In this Builder method, setState is the method corresponding to the setState of the corresponding state component, which is used to control the state of the component generated by StatefulBuilder. This approach is somewhat similar to the use of the React useState hook function.

Interface changes

First of all, the head component of the bottom popover should be replaced, and a confirmation button should be added. The method of building this component should be extracted as follows:

Widget _getModalSheetHeaderWithConfirm(String title,
      {Function onCancel, Function onConfirm}) {
  return SizedBox(
    height: 50,
    child: Row(
      children: [
        IconButton(
          icon: Icon(Icons.close),
          onPressed: () {
            onCancel();
          },
        ),
        Expanded(
          child: Center(
            child: Text(
              title,
              style: TextStyle(fontWeight: FontWeight.bold, fontSize: 16.0), ), ), ), IconButton( icon: Icon( Icons.check, color: Colors.blue, ), onPressed: () { onConfirm(); })],),); }Copy the code

With this method, you can pass in a header with an external parameter, cancel the response event callback, and confirm the event callback, which is more general.

Secondly, options need to be marked with ICONS. When selected, they are displayed as check boxes, and when not selected, they are blank boxes, which need to be controlled by status data. Here we use the Set type to ensure that the selected dataset is not duplicated. When clicking the option, if the index of the array corresponding to the option is in the Set, it will be removed from the Set, indicating that the selection is cancelled. If it is not in Set, it is added to the Set. This process requires the package to be in state to update the interface. Indicates whether the current index of the list element is in the Set, if yes, it is selected, if not, it is not selected.

Finally, the callback of the confirmation event converts the elements of the Set into an array, which is then used by the superior business to determine which data was selected using the selected subscript array.

Code implementation

Key code implementation is as follows, focusing on the use of StatefulBuilder and the use of Set data type corresponding to select and deselect operation business logic.

Future<List<int>> _showMultiChoiceModalBottomSheet(
      BuildContext context, List<String> options) async {
  Set<int> selected = Set<int> ();return showModalBottomSheet<List<int>>(
    backgroundColor: Colors.transparent,
    isScrollControlled: true,
    context: context,
    builder: (BuildContext context) {
      return StatefulBuilder(builder: (context1, setState) {
        return Container(
          clipBehavior: Clip.antiAlias,
          decoration: BoxDecoration(
            color: Colors.white,
            borderRadius: BorderRadius.only(
              topLeft: const Radius.circular(20.0),
              topRight: const Radius.circular(20.0),
            ),
          ),
          height: MediaQuery.of(context).size.height / 2.0,
          child: Column(children: [
            _getModalSheetHeaderWithConfirm('Multiple bottom popover', 
                onCancel: () {
                  Navigator.of(context).pop();
                }, 
                onConfirm: () {
                  Navigator.of(context).pop(selected.toList());
                },
            ),
            Divider(height: 1.0),
            Expanded(
              child: ListView.builder(
                itemBuilder: (BuildContext context, int index) {
                  return ListTile(
                    trailing: Icon(
                        selected.contains(index)
                            ? Icons.check_box
                            : Icons.check_box_outline_blank,
                        color: Theme.of(context).primaryColor),
                    title: Text(options[index]),
                    onTap: () {
                      setState(() {
                        if (selected.contains(index)) {
                          selected.remove(index);
                        } else{ selected.add(index); }}); }); }, itemCount: options.length, ), ), ]), ); }); }); }Copy the code

conclusion

This article describes how to implement multiple selection for bottom popups, which can be implemented in many ways, such as directly using stateful components in custom components. The method described here can be used as a reference to build stateful components dynamically to make it easy and quick to implement multiple selection of bottom popups.