Flutter用Getx关闭选定的对话框

时间:2020-09-11 05:16:39

标签: flutter

我使用flutter已有一段时间,最近使用Get来实现状态管理。 我先打开加载对话框,然后打开消息对话框时遇到问题。然后我想关闭加载对话框,但消息对话框是保持关闭状态的对话框。

import 'package:flutter/material.dart';
import 'package:get/get.dart';

class HomeController extends GetxController {

  Future<void> openAndCloseLoadingDialog() async {
    showDialog(
      context: Get.overlayContext,
      barrierDismissible: false,
      builder: (_) => WillPopScope(
        onWillPop: () async => false,
        child: Center(
          child: SizedBox(
            width: 60,
            height: 60,
            child: CircularProgressIndicator(
              strokeWidth: 10,
            ),
          ),
        ),
      ),
    );

    await Future.delayed(Duration(seconds: 3));

    Get.dialog(
      AlertDialog(
        title: Text("This should not be closed automatically"),
        content: Text("This should not be closed automatically"),
        actions: <Widget>[
          FlatButton(
            child: Text("CLOSE"),
            onPressed: () {
              Get.back();
            },
          )
        ],
      ),
      barrierDismissible: false,
    );

    await Future.delayed(Duration(seconds: 3));

    Navigator.of(Get.overlayContext).pop();
  }
}

上面的代码关闭了第二个对话框,而不是我想要的第一个对话框。 谁能在这件事上提供建议。

2 个答案:

答案 0 :(得分:3)

AlertDialog 而不是 CircularProgressIndicator 的原因是因为 AlertDialog 位于堆栈顶部。您可以在此处执行的是在显示 Navigator.of(Get.overlayContext).pop(); 之前调用 CircularProgressIndicator 以关闭 AlertDialog

Demo

基于提供的片段的示例代码。

import 'package:flutter/material.dart';
import 'package:get/get.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return GetMaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;
  final HomeController c = Get.put(HomeController());

  void _incrementCounter() {
    c.openAndCloseLoadingDialog();
    // setState(() {
    //   _counter++;
    // });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headline4,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ),
    );
  }
}

class HomeController extends GetxController {

  Future<void> openAndCloseLoadingDialog() async {
    showDialog(
      context: Get.overlayContext,
      barrierDismissible: false,
      builder: (_) => WillPopScope(
        onWillPop: () async => false,
        child: Center(
          child: SizedBox(
            width: 60,
            height: 60,
            child: CircularProgressIndicator(
              strokeWidth: 10,
            ),
          ),
        ),
      ),
    );

    await Future.delayed(Duration(seconds: 3));
    // Dismiss CircularProgressIndicator
    Navigator.of(Get.overlayContext).pop();

    Get.dialog(
      AlertDialog(
        title: Text("This should not be closed automatically"),
        content: Text("This should not be closed automatically"),
        actions: <Widget>[
          FlatButton(
            child: Text("CLOSE"),
            onPressed: () {
              Get.back();
            },
          )
        ],
      ),
      barrierDismissible: false,
    );

    // await Future.delayed(Duration(seconds: 3));
    // Navigator.of(Get.overlayContext).pop();
  }
}

答案 1 :(得分:0)

我认为,我使用OverlayEntry而不是Dialog来显示loadingIndicator: 这是我的代码:

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';

OverlayEntry _loaderEntry;

void showLoadingIndicator({@required BuildContext context}) {
  _loaderEntry = createOverlayEntry();
  Overlay.of(context).insert(_loaderEntry);
}

void hideLoadingIndicator() {
  _loaderEntry.remove();
}

OverlayEntry createOverlayEntry() {
  return OverlayEntry(
    builder: (context) {
      return Material(
        color: const Color(0x00000000),
        child: SafeArea(
          child: Stack(
            alignment: Alignment.center,
            children: [
              Container(
                color: Colors.transparent.withOpacity(0.3),
              ),
              Container(
                padding: const EdgeInsets.all(16.0),
                decoration: BoxDecoration(
                  color: Colors.black38,
                  borderRadius: BorderRadius.circular(10.0),
                ),
                child: Column(
                  mainAxisSize: MainAxisSize.min,
                  children: [
                    const Text('Loading ...'),
                    const SizedBox(
                      height: 8.0,
                    ),
                    const CircularProgressIndicator(),
                  ],
                ),
              ),
            ],
          ),
        ),
      );
    },
  );
}

您可以显示加载,处理任何内容,然后只需调用hideLoading()