在app主屏幕上显示警报对话框会自动加载

Wit*_*ult 11 android-alertdialog flutter flutter-layout

我想根据条件显示警告对话框.不基于按钮按下事件等用户交互.

如果在应用程序状态中设置了标志,则会显示数据警告对话框,否则不显示.

下面是我想要显示的示例警报对话框

  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();
              },
            ),
          ],
        );
      },
    );
  }
Run Code Online (Sandbox Code Playgroud)

我试图在主屏幕小部件的构建方法中调用该方法,但它给了我错误 -

 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)
Run Code Online (Sandbox Code Playgroud)

问题是我不知道从哪里调用_showDialog方法?

Cop*_*oad 17

只需覆盖initState_showDialog在内部调用您的方法Timer.run()

@override
void initState() {
  super.initState();
  Timer.run(() => _showDialog());
}
Run Code Online (Sandbox Code Playgroud)


Feu*_*Feu 13

我会把它放在initStatea State(of a StatefulWidget) 中。

将它放在小部件的build方法中Stateless很诱人,但这会多次触发您的警报。

在下面的这个例子中,当设备没有连接到 Wifi 时,它会显示一个警报,如果没有,则显示一个 [再试一次] 按钮。

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."),
          )
      );
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 我收到此错误`在 MainScreen.initState() 完成之前调用了 inheritedFromWidgetOfExactType(_InheritedTheme)` (5认同)
  • 你如何在 `_showAlert` 方法中传递 `context`? (2认同)
  • @Fue 是的,我做到了。我找到了解决方案,您的方法必须是“异步”。 (2认同)

Din*_*ian 8

你必须将内容包装在另一个内容中Widget(最好是无状态的).

例:

改变自:

  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"),
              )));
    }
  }
Run Code Online (Sandbox Code Playgroud)

对此:

  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"),
              ));
    }
  }
Run Code Online (Sandbox Code Playgroud)

注意:请参阅此处的包装显示警报Future.delayed(Duration.zero,..)

  • 将其放置在“ build”中的问题是,如果重绘了此MyHome小部件,它将再次触发“ alert”。 (4认同)
  • 您可以使用 bool var 仅输入一次该函数 (2认同)

小智 5

这就是我以简单的方式实现这一目标的方式:

  1. 添加https://pub.dev/packages/shared_preferences

  2. 在主屏幕(或任何所需小部件)的构建方法上方:

    Future checkFirstRun(BuildContext context) async {
     SharedPreferences prefs = await SharedPreferences.getInstance();
     bool isFirstRun = prefs.getBool('isFirstRun') ?? true;
    
     if (isFirstRun) {
       // Whatever you want to do, E.g. Navigator.push()
       prefs.setBool('isFirstRun', false);
     } else {
       return null;
     }
    }
    
    Run Code Online (Sandbox Code Playgroud)
  3. 然后在您的小部件的 initState 上:

    @override
    void initState() {
      super.initState();
      WidgetsBinding.instance.addPostFrameCallback((_) => checkFirstRun(context));
    }
    
    Run Code Online (Sandbox Code Playgroud)

这可确保在构建小部件后运行该函数。