Search code examples
flutterfuturedelayed-executionflutter-showmodalbottomsheet

showModelBottomSheet is not opening after Future.delay


I have two showModalBottomSheet(). In the First modalSheet there is a IconButton(). When the IconButton tapped, The First sheet should be closed and after 2 seconds the second modalSheet should be opened.

When I use the Future.delay function between the Navigator.pop(context) and the second showModalBottomSheet(), It throws some error and the second sheet is not opening.

Code:

IconButton(
           onPressed: () {
                        taskerFilterController.applyingLangaugePairChanges().whenComplete(
                          () {
                            Navigator.pop(context);
                            Future.delayed(const Duration(seconds: 2), () {
                              if (mainLayoutController.contactType == 1 && mainLayoutController.locationName.isEmpty) {
                                showModalBottomSheet(context: context, builder: (BuildContext context) => const TaskType(), isScrollControlled: true);
                              }
                            });
                          },
                        );
                      },
                      icon: const Icon(Icons.done, size: 25, color: kGreen)),

If I remove the Future.delay it was working fine or if I remove the Navigator.pop(context) it was fine but the first modalSheet has to be closed before opening the second modalSheet.

Error:

    Null check operator used on a null value
I/flutter (32026): #0      Element.widget (package:flutter/src/widgets/framework.dart:3483:31)
I/flutter (32026): #1      debugCheckHasMediaQuery.<anonymous closure> (package:flutter/src/widgets/debug.dart:296:17)
I/flutter (32026): #2      debugCheckHasMediaQuery (package:flutter/src/widgets/debug.dart:311:4)
I/flutter (32026): #3      showModalBottomSheet (package:flutter/src/material/bottom_sheet.dart:1254:10)
I/flutter (32026): #4      CatAndSubcat.build.<anonymous closure>.<anonymous closure>.<anonymous closure>.<anonymous closure> (package:tolk2go/Utility/cat_and_subcat.dart:37:33)
I/flutter (32026): #5      new Future.delayed.<anonymous closure> (dart:async/future.dart:422:39)
I/flutter (32026): #6      Timer._createTimer.<anonymous closure> (dart:async-patch/timer_patch.dart:18:15)
I/flutter (32026): #7      _Timer._runTimers (dart:isolate-patch/timer_impl.dart:398:19)
I/flutter (32026): #8      _Timer._handleMessage (dart:isolate-patch/timer_impl.dart:429:5)
I/flutter (32026): #9      _RawReceivePort._handleMessage (dart:isolate-patch/isolate_patch.dart:184:12)

How do solve this? Is there any way to close the showModalBottomSheet() without using the Navigator.pop(context)?


Solution

  • To show the second modal bottom sheet, use the context from the widget instead of the context from the first modal bottom sheet. To do this, you can rename the inner context to prevent variable shadowing.

    class MyWidget extends StatelessWidget {
      const MyWidget({super.key});
    
      @override
      Widget build(BuildContext context) {
        return FilledButton(
          onPressed: () {
            showModalBottomSheet(
              context: context,
              builder: (modalContext) { // Rename `context` to `modalContext`
                return IconButton(
                  onPressed: () {
                    Navigator.pop(modalContext); // Use `modalContext` to pop the first modal
                    Future.delayed(const Duration(seconds: 2), () {
                      showModalBottomSheet(
                        context: context, // This context is from MyWidget's build method
                        builder: (_) => const TaskType(),
                      );
                    });
                  },
                  icon: Icon(Icons.done),
                );
              },
            );
          },
          child: Text('Show first bottom sheet'),
        );
      }
    }