Flutter onClosing callback for showModalBottomShee

2020-06-12 05:29发布

I have a showModalBottomSheet like the below, which I understand to inherit from BottomSheet (right?)

      showModalBottomSheet<void>(
        context: context,
        builder: (BuildContext context) {
          return Container(
            height: 260.0,
            child: Text('I am text')
          );
        },
      );

What I want to do:

I want to know (listen) when the modal is being closed, and act on it.

I've seen this onClosing callback: https://docs.flutter.io/flutter/material/BottomSheet/onClosing.html

How can I have a listener attached to the showModalBottomSheet, and then act accordingly when it fires?

标签: dart flutter
6条回答
我只想做你的唯一
2楼-- · 2020-06-12 05:45
() async {

   // Save the bottomsheet in a variable

   var bottomSheet = showModalBottomSheet(
      context: context,
      builder: (context) => Container();
    );

   // Detect when it closes
   await bottomSheet.then((onValue) {
     print("value: $onValue");
   });

   // Do something here
}
查看更多
甜甜的少女心
3楼-- · 2020-06-12 05:48

showBottomSheet does not return a future, now it returns a PersistentBottomSheetController

  var _scaffoldKey = GlobalKey<ScaffoldState>();
  PersistentBottomSheetController persistentBottomSheetController;
 persistentBottomSheetController = _scaffoldKey.currentState.showBottomSheet<void>(
    (context)=>Container(

    )
 );
 persistentBottomSheetController.closed.then(_closeModal);
  void _closeModal(void value) {
    print('modal closed');
  }
查看更多
别忘想泡老子
4楼-- · 2020-06-12 05:54

Perhaps it's not the best solution, but showModalBottomSheet return a "Future" so you can used it.

For example:

void _showModal() {
    Future<void> future = showModalBottomSheet<void>(
      context: context,
      builder: (BuildContext context) {
        return Container(height: 260.0, child: Text('I am text'));
      },
    );
    future.then((void value) => _closeModal(value));
}
void _closeModal(void value) {
    print('modal closed');
}
查看更多
祖国的老花朵
5楼-- · 2020-06-12 05:55

Using async / await on showModalBottomSheet() close

You can do this with async / await instead of callbacks.

As per the documentation, showModalBottomSheet()

Returns a Future that resolves to the value (if any) that was passed to Navigator.pop when the modal bottom sheet was closed.

This means that we can "await" the showModelBottomSheet() to complete, and then use the value returned by the Navigator.pop() function used to close the sheet.

Because this is "waiting" for the sheet to be closed, your next function won't run until it's closed. In this example, we just call the print() function, but that could be any function you need. No callbacks are necessary in this case.

Tip: if it's critical that the user tap a "save and close" button to close the bottom sheet (instead of just tapping outside of it), you should use isDismissibile: false on the sheet.

In this example, we expect the sheet to return a string when it's closed.

Example Button To Open The showModalBottomSheet()

  FlatButton(
    child: Text("Show Bottom Sheet"),
    onPressed: () async {
      print("Showing bottom sheet...");
      String test = await showModalBottomSheet<String>(
        context: context,
        isDismissible: false,
        builder: (context) => Widget(),
      );
      print("Modal sheet closed with value: " + test);
    },
  ),

Example Button To Close The sheet, inside Widget()

FlatButton(
  child: Text("Save and Close"),
  onPressed: () {
    print("Closing sheet.");
    Navigator.pop(context, "This string will be passed back to the parent",);
  },
),

Example Log Outputs

flutter: Showing bottom sheet...
flutter: Closing sheet.
flutter: Modal sheet closed with value: This string will be passed back to the parent
查看更多
家丑人穷心不美
6楼-- · 2020-06-12 06:08

I personally think the accepted answer is not as sleek as it can be. A wiser idea is to do it native Dart way without any extra complexity:

() async {
      final result = await showModalBottomSheet(context: context, builder: (_) =>

      );
}

It also works with Navigator.of(context).pushNamed(). result variable value in my case is defined by the value you pass back on Navigator.of(context).pop({value}). You can return any kind of object and then make a simple if statement to make sure data is the one you want:

if(result != null && result == true) { ... }
查看更多
叼着烟拽天下
7楼-- · 2020-06-12 06:09

Old post but anyways, Might be helpful for you or others. So you can also achieve it by use of whenComplete function of showModalBottomSheet.

Let's see below code

showModalBottomSheet<void>(
        context: context,
        builder: (BuildContext context) {
          return Container(
            height: 260.0,
            child: Text('I am text')
        );
      },
).whenComplete(() {
  print('Hey there, I\'m calling after hide bottomSheet');
});

That's it.

查看更多
登录 后发表回答