Home > database >  Flutter | Have a modalbottomsheet and wish to extract it as a widget
Flutter | Have a modalbottomsheet and wish to extract it as a widget

Time:01-03

I am implementing a sort by function which displays sort options through a modal bottom sheet, I am able to do it in my "Home Page" widget. Would like to check if I can extract these codes and sub it as a widget for better organization. I am unable to do as I am concerned with the return values from the radio value.

Appreciate any help given, thanks!!

Here is my code:

child: TextButton.icon( // Button to press sort 
                                onPressed: (() {
                                  showModalBottomSheet( // show modal 
                                      shape: RoundedRectangleBorder(
                                          borderRadius:
                                              BorderRadius.circular(10.0)),
                                      context: context,
                                      builder: (BuildContext build) {
                                        return Column(
                                          mainAxisSize: MainAxisSize.min,
                                          children: <Widget>[ // radio values 
                                            RadioListTile(
                                              value: 1,
                                              groupValue: selectedRadioTile,
                                              title: Text(
                                                  "Case Earliest to Latest"),
                                              onChanged: (val) {
                                                print(
                                                    "Radio Tile pressed $val");
                                                setSelectedRadioTile(val!);
                                                print(selectedRadioTile);
                                                Navigator.pop(context);
                                              },
                                              activeColor:
                                                  constants.secondaryBlueColour,
                                            ),
                                            RadioListTile(
                                              value: 2,
                                              groupValue: selectedRadioTile,
                                              title: Text(
                                                  "Case Latest to Earliest "),
                                              onChanged: (val) {
                                                print(
                                                    "Radio Tile pressed $val");
                                                setSelectedRadioTile(val!);
                                                print(selectedRadioTile);
                                                Navigator.pop(context);
                                              },
                                              activeColor:
                                                  constants.secondaryBlueColour,
                                            )
                                          ],
                                        );
                                      });
                                }),
                                icon: Icon(
                                  Icons.sort,
                                  size: 28,
                                  color: constants.textGrayColour,
                                ),
                                label: Text("Sort",
                                    style: TextStyle(
                                        color: constants.textGrayColour,
                                        fontWeight: FontWeight.bold)))),***
                        Container(
                          margin: const EdgeInsets.only(top: 5),
                          width: MediaQuery.of(context).size.width * 0.5,
                          decoration: BoxDecoration(
                              border: Border(
                            left: BorderSide(
                                width: 2.0,
                                color:
                                    constants.categoryButtonBackgroundColour),
                            bottom: BorderSide(
                                width: 2.0,
                                color:
                                    constants.categoryButtonBackgroundColour),
                          )),
                          child: TextButton.icon(
                              onPressed: () {},
                              icon: Icon(Icons.filter_alt,
                                  size: 28, color: constants.textGrayColour),
                              label: Text("Filter",
                                  style: TextStyle(
                                      color: constants.textGrayColour,
                                      fontWeight: FontWeight.bold))),
                        ),
                      ],
                    ),
                   

I implemented a SortWidget() but am wondering how I can return the current radio value to my homepage and set the state in the homepage based on the radio value

CodePudding user response:

showModalBottomSheet is a future method, you can use async method for this. and Navigator.pop(context, value); will give you the result. you can also used callback method, seems not needed for your case.

onPressed:()async {
  final value = await showModalBottomSheet(
    shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10.0)),
    context: context,
    builder: (BuildContext build) {
      return MyBottomSheetWidget(selectedRadioTile: selectedRadioTile);
    },
  );
   print("$value");
}
class MyBottomSheetWidget extends StatelessWidget {
  // make it statefulWidget if you want to update dialog ui
  const MyBottomSheetWidget({
    Key? key,
    required this.selectedRadioTile,
  }) : super(key: key);

  final selectedRadioTile;

  @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisSize: MainAxisSize.min,
      children: <Widget>[
        // radio values
        RadioListTile(
          value: 1,
          groupValue: selectedRadioTile,
          title: Text("Case Earliest to Latest"),
          onChanged: (val) {
            print("Radio Tile pressed $val");

            Navigator.pop(context, val);
          },
        ),
        RadioListTile(
          value: 2,
          groupValue: selectedRadioTile,
          title: Text("Case Latest to Earliest "),
          onChanged: (val) {
            print("Radio Tile pressed $val");
            // setSelectedRadioTile(val!);
            print(selectedRadioTile);
            Navigator.pop(context, val);
          },
        )
      ],
    );
  }
}

CodePudding user response:

showModalBottomSheet is actually a function which can't converted to widget without having some other widget in place. What you can do is, create a function which hold code of this showModalBottomSheet and call that function on button click.

But if you want to create a separate widget then you can create the widget from the internal code of the showModalBottomSheet which starts with return Column.

You need to create a widget which can take two properties which are int variable named selected and a Function named setSelected. Then you can call that widget from inside the showModalBottomSheet and pass two props from your page. This selected will be set as selectedRadioTile & setSelected will be set as setSelectedRadioTile.

Example Code

class BottomFilter extends StatelessWidget {
  const BottomFilter(
      {Key? key,
      required this.selected,
      required this.setSelected})
      : super(key: key);

  final int selected;
  final Function setSelected;
  @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisSize: MainAxisSize.min,
      children: <Widget>[
        // radio values
        RadioListTile(
          value: 1,
          groupValue: selected,
          title: Text("Case Earliest to Latest"),
          onChanged: (val) {
            print("Radio Tile pressed $val");
            setSelected(val!);
            print(selected);
            Navigator.pop(context);
          },
          activeColor: Colors.amber,
        ),
        RadioListTile(
          value: 2,
          groupValue: selected,
          title: Text("Case Latest to Earliest "),
          onChanged: (val) {
            print("Radio Tile pressed $val");
            setSelected(val!);
            print(selected);
            Navigator.pop(context);
          },
          activeColor: Colors.amber,
        )
      ],
    );
  }
}

Call it like this

builder: (BuildContext build) {
          return BottomFilter(selected: selectedRadioTile, setSelected:  setSelectedRadioTile);
        })

Dartpad link to test this code https://dartpad.dev/?id=e75b493dae1287757c5e1d77a0dc73f1

  • Related