Actuellement, il est très difficile d'afficher le dialogue de n'importe quelle couche de code dans l'application simplement parce qu'il faut y passer le contexte. Par conséquent, j'ai pensé à passer navigatorKey.currentContext (la clé Navigator est une clé globale transmise au paramètre NavigatorKey de l'application Material) pour afficher la boîte de dialogue. Mais j'ai l'erreur
"Opération de navigateur demandée avec un contexte qui n'inclut pas de navigateur. Le contexte utilisé pour pousser ou afficher des routes à partir du navigateur doit être celui d'un widget qui est un descendant d'un widget de navigateur."
Le problème est que showDialog appelle Navigator.of (context) en interne et qui recherche l'ancêtre du navigateur qui, bien sûr, retournera null car le navigateur est lui-même la racine. Il ne trouvera donc pas le navigateur comme ancêtre.
Existe-t-il un moyen de transmettre directement l'état / le contexte du navigateur à la fonction showDialog pour afficher la boîte de dialogue? Ou y a-t-il un moyen plus simple de montrer Dialog sans lui passer de contexte si nous voulons le montrer à partir d'un bloc?
4 Réponses :
Actuellement, je montre une boîte de dialogue en créant une fonction dans ma classe util qui prend le contexte comme paramètre.
static void showAlertDialog(String title, String message, BuildContext context) { // flutter defined function showDialog( context: context, builder: (BuildContext context) { // return object of type Dialog return AlertDialog( title: new Text(title), content: new Text(message), actions: <Widget>[ // usually buttons at the bottom of the dialog new FlatButton( child: new Text("Close"), onPressed: () { Navigator.of(context).pop(); }, ), ], ); }, ); }
Utilisation de la fonction ci-dessus comme: UtilClass. showAlertDialog("Title", "Message", context);
Voir les problèmes était de passer le contexte dans le dialogue et non la façon d'afficher le dialogue. Veuillez me dire un moyen de transmettre le contexte sans réellement passer le contexte à cette méthode à chaque fois
Vous pouvez utiliser InheritedWidget
ici. Faites d'un InheritedWidget
la racine de votre application qui contient une clé de navigateur. Ensuite, vous pouvez transmettre n'importe quel context
de widgets enfants pour obtenir l'état actuel du navigateur.
Exemple:
InheritedWidget:
NavigatorStateFromKeyOrContext.of(context)
Écran d'accueil:
final GlobalKey navigator = GlobalKey<NavigatorState>(debugLabel: 'AppNavigator'); runApp( NavigatorStateFromKeyOrContext( navigatorKey: navigator, child: HomePage(), ), );
La racine de l'application ressemblera à,
// Your home screen class HomePage extends StatefulWidget { @override _HomePageState createState() => _HomePageState(); } class _HomePageState extends State<HomePage> { @override Widget build(BuildContext context) { return MaterialApp( navigatorKey: NavigatorStateFromKeyOrContext.getKey(context), home: InitPage(), ); } }
Maintenant, de n'importe où dans l'application, transmettez n'importe quel contexte pour obtenir le NavigatorState
comme
// Your InheritedWidget class NavigatorStateFromKeyOrContext extends InheritedWidget { const NavigatorStateFromKeyOrContext({ Key key, @required this.navigatorKey, @required Widget child, }) : super(key: key, child: child); final GlobalKey<NavigatorState> navigatorKey; static GlobalKey<NavigatorState> getKey(BuildContext context) { final NavigatorStateFromKeyOrContext provider = context.inheritFromWidgetOfExactType(NavigatorStateFromKeyOrContext); return provider.navigatorKey; } static NavigatorState of(BuildContext context) { NavigatorState state; try { state = Navigator.of(context); } catch (e) { // Assertion error thrown in debug mode, in release mode no errors are thrown print(e); } if (state != null) { // state can be null when context does not include a Navigator in release mode return state; } final NavigatorStateFromKeyOrContext provider = context.inheritFromWidgetOfExactType(NavigatorStateFromKeyOrContext); return provider.navigatorKey?.currentState; } @override bool updateShouldNotify(NavigatorStateFromKeyOrContext oldWidget) { return navigatorKey != oldWidget.navigatorKey; } }
Remarque: C'est une approche que j'ai proposée dans laquelle j'ai utilisé InheritedWidget
, il existe de nombreuses autres façons d'y parvenir, comme utiliser Singleton
, avoir un bloc global pour fournir la clé de navigateur, stocker la clé de navigateur dans un magasin Redux
ou tout autre solutions de gestion d'état, etc.
J'espère que cela t'aides!
voir le problème n'est pas d'accéder à la clé de navigateur. Je peux facilement y accéder en en faisant simplement une fonction de haut niveau ou simplement statique. Le problème est que le retour de contexte par navigatorKey.currentState ne contient pas Navigator comme ancêtre mais lui-même le navigateur uniquement
Oui, je comprends parfaitement cela. Cela se produit lorsque le contexte que vous passez n'a pas de Navigator
comme parent, c'est-à-dire que votre application n'est pas une MaterialApp
ou que vous n'avez pas de parent Navigator
pour cet enfant quelque part en haut de l'arborescence. Cela devrait donner accès au navigateur sans aucune erreur que vous obtenez actuellement. Veuillez essayer ceci, ou au moins publier un code expliquant comment vous l'utilisez. Ce sera utile de résoudre. Merci :)
J'ai trouvé une solution simple:
navigatorKey.currentState.overlay.context
J'utilise cela dans un middleware redux où je garde navigatorKey et je souhaite afficher une boîte de dialogue globalement n'importe où dans l'application chaque fois que j'expédie une action spécifique.
cela semble intéressant. va le vérifier
pendant que je passe Contexte et non Buildcontext, j'obtiens cette erreur: Tapez «Contexte» introuvable.
Depuis que celui-ci est fusionné: https://github.com/flutter/flutter/pull/58259
Vous pouvez utiliser:
navigatorKey.currentContext;
Agréable. Nous pouvons donc maintenant utiliser ci-dessus au lieu de navigatorKey.currentState.overlay.context
. Droite?