web-dev-qa-db-fra.com

Afficher la boîte de dialogue d'alerte sur l'écran principal de l'application

Je souhaite afficher un dialogue d'alerte basé sur une condition. Ne repose pas sur une interaction de l'utilisateur telle qu'un événement de pression de bouton.

Si un indicateur est défini dans l'application, une boîte de dialogue d'alerte de données s'affiche, sinon ce n'est pas le cas.

Vous trouverez ci-dessous un exemple de dialogue d'alerte que je souhaite afficher.

  void _showDialog() {
    // flutter defined function
    showDialog(
      context: context,
      builder: (BuildContext context) {
        // return object of type Dialog
        return AlertDialog(
          title: new Text("Alert Dialog title"),
          content: new Text("Alert Dialog body"),
          actions: <Widget>[
            // usually buttons at the bottom of the dialog
            new FlatButton(
              child: new Text("Close"),
              onPressed: () {
                Navigator.of(context).pop();
              },
            ),
          ],
        );
      },
    );
  }

J'ai essayé d'appeler cette méthode dans la méthode de construction du widget de l'écran principal mais cela me donne une erreur -

 The context used to Push or pop routes from the Navigator must be that of a widget that is a descendant of a Navigator widget.
E/flutter ( 3667): #0      Navigator.of.<anonymous closure> (package:flutter/src/widgets/navigator.Dart:1179:9)
E/flutter ( 3667): #1      Navigator.of (package:flutter/src/widgets/navigator.Dart:1186:6)
E/flutter ( 3667): #2      showDialog (package:flutter/src/material/dialog.Dart:642:20)

Le problème est que je ne sais pas d'où je devrais appeler cette méthode _showDialog?

10
WitVault

Je le placerais dans initState d'un State (d'un StatefulWidget).

Le placer dans la méthode build d'un widget Stateless est tentant, mais cela déclenchera votre alerte plusieurs fois.

Dans l'exemple ci-dessous, il affiche une alerte lorsque l'appareil n'est pas connecté au réseau Wi-Fi et affiche un bouton [Réessayer] s'il ne l'est pas.

import 'package:flutter/material.Dart';
import 'package:connectivity/connectivity.Dart';

void main() => runApp(MaterialApp(title: "Wifi Check", home: MyPage()));

class MyPage extends StatefulWidget {
    @override
    _MyPageState createState() => _MyPageState();
}

class _MyPageState extends State<MyPage> {
    bool _tryAgain = false;

    @override
    void initState() {
      super.initState();
      _checkWifi();
    }

    _checkWifi() async {
      // the method below returns a Future
      var connectivityResult = await (new Connectivity().checkConnectivity());
      bool connectedToWifi = (connectivityResult == ConnectivityResult.wifi);
      if (!connectedToWifi) {
        _showAlert(context);
      }
      if (_tryAgain != !connectedToWifi) {
        setState(() => _tryAgain = !connectedToWifi);
      }
    }

    @override
    Widget build(BuildContext context) {
      var body = Container(
        alignment: Alignment.center,
        child: _tryAgain
          ? RaisedButton(
              child: Text("Try again"),
              onPressed: () {
                _checkWifi();
            })
          : Text("This device is connected to Wifi"),
      );

      return Scaffold(
        appBar: AppBar(title: Text("Wifi check")),
        body: body
      );
    }

    void _showAlert(BuildContext context) {
      showDialog(
          context: context,
          builder: (context) => AlertDialog(
            title: Text("Wifi"),
            content: Text("Wifi not detected. Please activate it."),
          )
      );
    }
}
3
Feu

Vous devez envelopper le contenu dans un autre Widget (de préférence sans état).

Exemple:

Changer de:

  import 'package:flutter/material.Dart';

  void main() {
    runApp(new MyApp());
  }

  class MyApp extends StatelessWidget {
    @override
    Widget build(BuildContext context) {
      return MaterialApp(
          title: 'Trial',
          home: Scaffold(
              appBar: AppBar(title: Text('List scroll')),
              body: Container(
                child: Text("Hello world"),
              )));
    }
  }

à ceci:

  import 'Dart:async';
  import 'package:flutter/material.Dart';

  void main() {
    runApp(new MyApp());
  }

  class MyApp extends StatelessWidget {
    @override
    Widget build(BuildContext context) {
      return MaterialApp(
          title: 'Trial',
          home: Scaffold(
              appBar: AppBar(title: Text('List scroll')), body: new MyHome()));
    }
  }

  class MyHome extends StatelessWidget { // Wrapper Widget
    @override
    Widget build(BuildContext context) {
      Future.delayed(Duration.zero, () => showAlert(context));
      return Container(
        child: Text("Hello world"),
      );
    }

    void showAlert(BuildContext context) {
      showDialog(
          context: context,
          builder: (context) => AlertDialog(
                content: Text("hi"),
              ));
    }
  }

Remarque: Reportez-vous à ici pour envelopper show alert dans Future.delayed(Duration.zero,..)

8