根窗口小部件的showDialog

szo*_*otp 4 flutter

我想显示一个来自根窗口小部件(创建MaterialApp的窗口)的对话框,我有一个NavigatorState实例,但是showDialog需要返回的上下文Navigator.of(context)

看起来我需要从路由提供上下文,但是我不能这样做,因为根窗口小部件没有它。

编辑:我发现了一种解决方法:我可以将仅存在的伪路由推送到showDialog,然后在对话框完成时弹出该路由。不漂亮,但可以。

szo*_*otp 21

我使用解决了问题navigator.overlay.context。这是示例:

import 'package:flutter/material.dart';

void main() => runApp(new MyApp());

class MyApp extends StatelessWidget {
  final navigatorKey = GlobalKey<NavigatorState>();

  void show() {
    final context = navigatorKey.currentState.overlay.context;
    final dialog = AlertDialog(
      content: Text('Test'),
    );
    showDialog(context: context, builder: (x) => dialog);
  }

  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      navigatorKey: navigatorKey,
      theme: new ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: Scaffold(
        appBar: AppBar(),
        body: FlatButton(
          child: Text('Show alert'),
          onPressed: show,
        ),
      ),
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

  • 谢谢,“navigatorKey.currentState.overlay.context;”成功了。 (2认同)

Nik*_*las 5

tl; dr:如果showDialog要从根窗口小部件调用,请将代码扩展到另一个窗口小部件(例如StatelessWidget)中,然后showDialog在此处调用。

无论如何,在下文中,我将假设您遇到了此问题:

flutter: No MaterialLocalizations found. 
flutter: MyApp widgets require MaterialLocalizations to be provided by a Localizations widget ancestor. 
flutter: Localizations are used to generate many different messages, labels,and abbreviations which are used by the material library.
Run Code Online (Sandbox Code Playgroud)

如前所述,showDialog只能在其祖先具有MaterialAppBuildContext中调用。因此,如果您具有以下结构,则无法直接调用:showDialog

- MaterialApp
  - Scaffold
    - Button // call show Dialog here
Run Code Online (Sandbox Code Playgroud)

在一个代码示例中,这将导致这样的代码,并抛出上面给出的错误:

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData(),
      home: Scaffold(
        body: Center(
          child: RaisedButton(
              child: Text('Show dialog!'),
              onPressed: () {
                showDialog(
                    context: context,
                    builder: (BuildContext context) {
                      return Dialog(
                        child: Text('Dialog.'),
                      );
                    });
              }),
        ),
      ),
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

要解决此错误,您可以创建一个新的Widget,它有自己的BuildContext。修改后的结构如下所示:

- MaterialApp
  - Home

- Home     // your own (Stateless)Widget
  - Button // call show Dialog here
Run Code Online (Sandbox Code Playgroud)

将代码示例修改为上面给出的结构,将得到下面的代码片段。showDialog可以调用而不会引发错误。

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData(),
      home: Home()
    );
  }
}

class Home extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: RaisedButton(
            child: Text('Show dialog!'),
            onPressed: () {
              showDialog(
                  context: context,
                  builder: (BuildContext context) {
                    return Dialog(
                      child: Text('Dialog.'),
                    );
                  });
            }),
      ),
    );
  }
}
Run Code Online (Sandbox Code Playgroud)