Flutter => showDialog / AlertDialog => No Material

2020-07-06 02:01发布

问题:

just new to Flutter but very impressed. I want to show a Dialog if a PushNotification arrives via Firebase "onMessage".

But every Time I get a Exception "No MaterialLocalizations found." if trying to show my Dialog. For testing I added a RaisedButton to show this Alert, but same problem. Perhaps somebody can help me. Thanks a lot!!!

Here is my whole code for the small app:

import 'dart:async';

import 'package:firebase_messaging/firebase_messaging.dart';

import 'package:flutter/material.dart';

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

class Main extends StatefulWidget {
  @override
  _MainState createState() => _MainState();
}

class _MainState extends State<Main> {
  final FirebaseMessaging _firebaseMessaging = FirebaseMessaging();

  Widget _buildDialog(BuildContext context) {
    print("_buildDialog");
    return AlertDialog(
      content: Text("Item  has been updated"),
      actions: <Widget>[
        FlatButton(
          child: const Text('CLOSE'),
          onPressed: () {
            Navigator.pop(context, false);
          },
        ),
        FlatButton(
          child: const Text('SHOW'),
          onPressed: () {
            Navigator.pop(context, true);
          },
        ),
      ],
    );
  }

  void _showPushDialog() {
    print("DIALOG");
    showDialog<bool>(
      context: context,
      builder: (_) => _buildDialog(context),
    ).then((bool shouldNavigate) {
      if (shouldNavigate == true) {
        _navigateToPushDetail();
      }
    });
  }

  void _navigateToPushDetail() {
    print("TODO: Goto...");
  }

  @override
  void initState() {
    super.initState();
    _firebaseMessaging.configure(
      onMessage: (Map<String, dynamic> message) async {
        print("onMessage: $message");
        //_neverSatisfied();
        _showPushDialog();
      },
      onLaunch: (Map<String, dynamic> message) async {
        print("onLaunch: $message");
        _navigateToPushDetail();
      },
      onResume: (Map<String, dynamic> message) async {
        print("onResume: $message");
        _navigateToPushDetail();
      },
    );

    _firebaseMessaging.requestNotificationPermissions(
        const IosNotificationSettings(sound: true, badge: true, alert: true));
    _firebaseMessaging.onIosSettingsRegistered
        .listen((IosNotificationSettings settings) {
      print("Settings registered: $settings");
    });
    _firebaseMessaging.getToken().then((String token) {
      assert(token != null);
      print("Push Messaging token: $token");
    });
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Welcome to Flutter',
      home: Scaffold(
        appBar: AppBar(
          title: Text('Welcome to Flutter'),
        ),
        body: new Material(
          child: Column(children: <Widget>[
            Center(
              child: Text('Hello World'),
            ),
            RaisedButton(
              onPressed: () {
                print("pushed?");
                _showPushDialog();
              },
              child: Text("press me"),
            )
          ]),
        ),
      ),
    );
  }
}

回答1:

In Order to Fix the error, You need to Call Your Main class as a home parameter of MaterialAppas Like Below.

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Welcome to Flutter',
      debugShowCheckedModeBanner: false,
      home: Main(),
    );
  }
}

& update your Build Method in Main Class as:

@override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Welcome to Flutter'),
      ),
      body: Column(children: <Widget>[
        Center(
          child: Text('Hello World'),
        ),
        RaisedButton(
          onPressed: () {
            print("pushed?");
            _showPushDialog(context);
          },
          child: Text("press me"),
        )
      ]),
    );
  }


回答2:

Flutter 1.0, Dart 2.x

This solution works on both StatelessWidget widget and StatefulWidget widget.

On the top, in your declaration you can create a static navKey:

class MyApp extends StatefulWidget {
  final String title; // sample var you want to pass to your widget
  static final navKey = new GlobalKey<NavigatorState>();
  const MyApp({Key navKey, this.title}) : super(key: navKey);
  @override
  State<StatefulWidget> createState() => _MyAppState();
}

On the layout part you should use the key:

return MaterialApp(
        navigatorKey:MyApp.navKey,
        title: widget.title,
        ...

So, when you need the current context for your dialog or other widget, in the state part you can do :

@override
  void initState() {
  final context = MyApp.navKey.currentState.overlay.context;
  showMyCustomDialog(context);
  ...
  super.initState();
}


回答3:

check your MaterialApp() widget, if you set localizationsDelegates ,may be you well get this problem. it works when i delete those code.

              localizationsDelegates: [
                  DefaultCupertinoLocalizations.delegate,
              ],

my codes.

MaterialApp(
              navigatorKey: navigatorKey,
              title: 'test',
              theme: ThemeData(
                  platform: TargetPlatform.iOS,
                  backgroundColor: Color(0xfff1f1f1),
                  accentColor: AppStyle.colorPrimary,
                  primaryColor: AppStyle.colorPrimary,
                  buttonColor: AppStyle.colorPrimary,
                  iconTheme: IconThemeData(color: Colors.white),
                  textTheme: TextTheme(
                      title: TextStyle(color: Colors.white),
                  ),
                  primaryTextTheme: TextTheme(title: TextStyle(color: Colors.white)),
                  primaryIconTheme: const IconThemeData.fallback().copyWith(
                      color: Colors.white,
                  ),
                  appBarTheme: AppBarTheme().copyWith(brightness: Brightness.dark),
              ),
              home: LoginPage(),
              debugShowCheckedModeBanner: false,
              onGenerateRoute: AppRouter.router.generator,
          )



标签: flutter