0

Flutter reference documentation shows an example of using CupertinoPicker class wrapped by CupertinoModalPopupRoute popup Dialog: https://api.flutter.dev/flutter/cupertino/CupertinoPicker-class.html (dartpad snippet available)

The Dialog with a CupertinoPicker pops up, once a button is clicked. Button's onPressed calls:

  void _showDialog(Widget child) {
    showCupertinoModalPopup<void>(
        context: context,
        builder: (BuildContext context) => Container(
              // some UI setting omitted 
              child: SafeArea(
                top: false,
                child: child,
              ),
            ));
  }

where child is:

  CupertinoPicker(
    // some UI setting omitted 
    onSelectedItemChanged: (int selectedItem) {
      setState(() {
        _selectedFruit = selectedItem;
      });
    },
    children:
        List<Widget>.generate(_fruitNames.length, (int index) {
      return Center(
        child: Text(
          _fruitNames[index],
        ),
      );
    }),
  ),
    

Method showCupertinoModalPopup used to push a Dialog with a Picker just above the main page.

  1. Method's annotation mentions that "Content below the widget is dimmed with a [ModalBarrier]", and exactly ModalBarrier's handleDismiss method is called once user taps outside the Dialog's area, this leads to Navigator.pop being called, which pops the Dialog returning default void value (I cannot find a way to pass custom callback to the ModalBarrier)
  2. Again from the showCupertinoModalPopup's annotation: "Returns a Future that resolves to the value that was passed to [Navigator.pop] when the popup was closed."

So the question is, what is the right way (if any) to override Navigator.pop to make showCupertinoModalPopup return a value? I don't want to use Picker's onSelectedItemChanged as it constantly changes the state while user choses right value.

Instead I would use it like:

Future<void> _showDialog(Widget child) async {
    int? value = await showCupertinoModalPopup<int>(
        context: context,
        builder: (BuildContext context) => Container(
             //omitted
              child: SafeArea(
                top: false,
                child: child,
              ),
            ));

    setState(() {
      Provider.of<FruitsController>(context, listen: false).currentFruit = value;
    });
  }

I would appreciate your help.

Md. Yeasin Sheikh
  • 54,221
  • 7
  • 29
  • 56
a_dmitted
  • 83
  • 8

1 Answers1

0

Yes you can create a button to pop from showCupertinoModalPopup.

  Future<void> _showDialog() async {
    int? value = await showCupertinoModalPopup<int>(
      context: context,
      builder: (BuildContext context) => Column(
        children: [
          ElevatedButton(
              onPressed: () {
                Navigator.of(context).pop(-2); //pasing value on pop is -2
              },
              child: Text("Close ")),
          Container(
            child: SafeArea(
              top: false,
              child: CupertinoPicker(
                onSelectedItemChanged: (int selectedItem) {
                  _selectedFruit = _fruitNames[selectedItem];
                },
                itemExtent: 33,
                children:
                    List<Widget>.generate(_fruitNames.length, (int index) {
                  return Center(
                    child: Text(
                      _fruitNames[index],
                    ),
                  );
                }),
              ),
            ),
          ),
        ],
      ),
    );

    print(value);
  }

Md. Yeasin Sheikh
  • 54,221
  • 7
  • 29
  • 56
  • Thank you for your reply. You are right, it is possible to add a button, even documentation says CupertinoActionSheet is the widget, which is usually returned by Dialog's builder, and this widget has a cancelButton by default. I assumed that the minimalistic approach without any button suggested by Flutter documentation is also valid and there is a way to intercept dialog closure initiated by ModalBarrier. – a_dmitted Aug 13 '22 at 07:17
  • Maybe I missed the default button, can you simplify in single snippet for web – Md. Yeasin Sheikh Aug 13 '22 at 08:35
  • @a_dmitted, Did you ever figure this out? I'd love to pop a value without needing button. Popping when clicking outside the picker are would be ideal. – eysikal Dec 27 '22 at 03:22