Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flutter: showGeneralDialog does not share a context with the location that showGeneralDialog is originally called from

Problem:

My showGeneralDialog-creation method looks like this: (I'm animating the onShow and onPop of the dialog, that's why I use the transitionbuilder instead of the pagebuilder)

  void _showSignOutAlert(BuildContext context) {
    showGeneralDialog(
      barrierColor: Colors.black.withOpacity(0.5),
      transitionBuilder: (context, a1, a2, widget) {
        return Transform.scale(
          scale: a1.value,
          child: Opacity(
            opacity: a1.value,
            child: CustomWidget(),
          ),
        );
      },
      transitionDuration: Duration(milliseconds: 250),
      barrierDismissible: true,
      context: context,
      pageBuilder: (context, animation1, animation2) {
        return null;
      },
    );
  }

I'm calling _showSignOutAlert() from a StatelessWidget passing along the StatelessWidget-context in the parameter.

I'm using the Provider-package and defined the ChangeNotifierProvider-builder above the StatelessWidget which calls the _showSignOutAlert()

When trying to access the Provider from the CustomWidget created by showGeneralDialog(), it's says it couldn't find the Provider.

From the flutter docs about showGeneralDialog():

This function takes a pageBuilder which is used to build the primary content of the route (typically a dialog widget). Content below the dialog is dimmed with a [ModalBarrier]. The widget returned by the pageBuilder does not share a context with the location that showGeneralDialog is originally called from. Use a [StatefulBuilder] or a custom [StatefulWidget] if the dialog needs to update dynamically. The pageBuilder argument can not be null.

Question:

I don't really get how I should proceed to be able to access the Provider from the CustomWidget?

like image 660
SimonartM Avatar asked Oct 15 '25 13:10

SimonartM


2 Answers

correct way :

void _showSignOutAlert(BuildContext context) {
  final CapturedThemes themes = InheritedTheme.capture(
    from: context,
    to: Navigator.of(
        context,
        rootNavigator: true,
    ).context,
  );

  showGeneralDialog(
    barrierColor: Colors.black.withOpacity(0.5),
    transitionBuilder: (context, a1, a2, widget) {
      return Transform.scale(
        scale: a1.value,
        child: Opacity(
          opacity: a1.value,
          child: widget,
        ),
      );
    },
    transitionDuration: Duration(milliseconds: 250),
    barrierDismissible: true,
    context: context,
    pageBuilder: (context, animation1, animation2) {
      return themes.wrap(Builder(
        builder: (context) => CustomWidget(),
      ));
    },
  );
}

pay attention to :

CapturedThemes and themes.wrap

like image 169
DJafari Avatar answered Oct 18 '25 07:10

DJafari


put useRootNavigator to false

https://api.flutter.dev/flutter/widgets/showGeneralDialog.html

The useRootNavigator argument is used to determine whether to push the dialog to the Navigator furthest from or nearest to the given context. By default, useRootNavigator is true and the dialog route created by this method is pushed to the root navigator.

like image 24
Gemu Avatar answered Oct 18 '25 06:10

Gemu