2

I am opening a dialog from another dialog and trying to close the 1st dialog, but it is closing the recent dialog. Similar kind of git issue.

I've tried

  • putting ValueKey on AlertDialog
  • using rootNavigator:true while pop
  • keeping context into variable and doing Navigator.of(specifiqContext).pop()

But none of them is working. Code to reproduce the issue on dartPad.

class MultiDialogTest extends StatefulWidget {
  const MultiDialogTest({Key? key}) : super(key: key);

  @override
  State<MultiDialogTest> createState() => _MultiDialogTestState();
}

class _MultiDialogTestState extends State<MultiDialogTest> {
  BuildContext? dialog1Context, dialog2Context;

  Future<void> _showDialog1(BuildContext context) async {
    await showDialog(
        context: context,
        barrierDismissible: false,
        builder: (c) {
          dialog1Context = c;
          return AlertDialog(
            key: const ValueKey("dialog 1"),
            title: const Text("Dialog 1"),
            content: ElevatedButton(
              child: const Text("close dialog2"),
              onPressed: () {
                if (dialog2Context != null) {
                  Navigator.of(dialog2Context!,).pop();
                }
              },
            ),
            actions: [
              ElevatedButton(
                child: const Text("close this"),
                onPressed: () {
                  Navigator.of(c, rootNavigator: true).pop();
                },
              ),
            ],
          );
        });

    dialog1Context = null;
  }

  Future<void> _showDialog2(BuildContext context) async {
    await showDialog(
        context: context,
        barrierDismissible: false,
        builder: (c) {
          dialog2Context = c;
          return AlertDialog(
            key: const ValueKey("dialog 2"),
            title: const Text("Dialog 2"),
            actions: [
              ElevatedButton(
                child: const Text("close this"),
                onPressed: () {
                  Navigator.of(c, rootNavigator: true).pop();
                },
              ),
            ],
            content: Column(
              children: [
                ElevatedButton(
                  onPressed: () async {
                    await _showDialog1(context);
                  },
                  child: const Text("Open dialog 1"),
                ),
              ],
            ),
          );
        });
    dialog2Context = null;
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            _showDialog2(context);
          },
          child: const Text("show dialog 2"),
        ),
      ),
    );
  }
}

How can I close bellow Dialog(Dialog 2) without closing above(Dialog 1).

I don't like to close both and reopen the Dialog 1.

enter image description here

4

4 回答 4

0

创建一个单独的上下文并将要关闭的正确上下文传递给 Navigator.pop(yourContextThatYouWishToClose)

Navigator.pop(dialogContext);

这是示例代码。

BuildContext dialogContext; // <<----
  showDialog(
    context: context, // <<----
    barrierDismissible: false,
    builder: (BuildContext context) {
      dialogContext = context;
      return Dialog(
        child: new Row(
          mainAxisSize: MainAxisSize.min,
          children: [
            new CircularProgressIndicator(),
            new Text("Loading"),
          ],
        ),
      );
    },
  );

  await _longOperation();
  Navigator.pop(dialogContext);
于 2022-02-17T09:26:40.397 回答
0

您需要传递要关闭的对话框的上下文(parentContext)并调用:

Navigator.pop(parentContext); // close parent 
Navigator.pop(context); // close current 
于 2022-02-17T09:34:44.163 回答
0

你可以做的是弹出两次showDialog1然后showDialog1立即等待。

import 'package:flutter/material.dart';
const Color darkBlue = Color.fromARGB(255, 18, 32, 47);

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData.dark().copyWith(
        scaffoldBackgroundColor: darkBlue,
      ),
      debugShowCheckedModeBanner: false,
      home: const MultiDialogTest(),
    );
  }
}

 
class MultiDialogTest extends StatefulWidget {
  const MultiDialogTest({Key? key}) : super(key: key);

  @override
  State<MultiDialogTest> createState() => _MultiDialogTestState();
}

class _MultiDialogTestState extends State<MultiDialogTest> {

  Future<void> _showDialog1(BuildContext context) async {
    await showDialog(
        context: context,
        barrierDismissible: false,
        builder: (c) {
          return AlertDialog(
            key: const ValueKey("dialog 1"),
            title: const Text("Dialog 1"),
            content: ElevatedButton(
              child: const Text("close dialog2"),
              onPressed: () async {
                  Navigator.of(context).pop();
                  Navigator.of(context).pop();
                  await _showDialog1(context);
              },
            ),
            actions: [
              ElevatedButton(
                child: const Text("close this"),
                onPressed: () {
                  Navigator.of(c).pop();
                },
              ),
            ],
          );
        });
  }

  Future<void> _showDialog2(BuildContext context) async {
    await showDialog(
        context: context,
        barrierDismissible: false,
        builder: (c) {
          return AlertDialog(
            key: const ValueKey("dialog 2"),
            title: const Text("Dialog 2"),
            actions: [
              ElevatedButton(
                child: const Text("close this"),
                onPressed: () {
                  Navigator.of(c).pop();
                },
              ),
            ],
            content: Column(
              children: [
                ElevatedButton(
                  onPressed: () async {
                    await _showDialog1(context);
                  },
                  child: const Text("Open dialog 1"),
                ),
              ],
            ),
          );
        });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            _showDialog2(context);
          },
          child: const Text("show dialog 2"),
        ),
      ),
    );
  }
}
于 2022-02-17T09:36:24.210 回答
0

当您使用showDialog引擎盖下发生的事情时,只需在导航器上进行简单的推送,这将在当前顶部添加对话框Navigator作为新路线。

所有的 pop 方法都是Navigator从最顶层的路由简单地弹出,所以这不容易实现。

一个肮脏的技巧可能是弹出两次并再次显示第一个对话框,如在您的 dartpad 示例中工作的此示例中

onPressed: () {
  if (dialog2Context != null) {
       Navigator.of(dialog2Context!).pop();
       Navigator.of(dialog2Context!).pop();
       _showDialog1(context);
  }
},

在我看来,让一个对话框产生另一个对话框并不是您可以提供给用户的最佳 UX,但您始终可以使用检查器检查涉及哪些路由:

https://docs.flutter.dev/development/tools/devtools/inspector

在这种情况下,您可以快速检查对话框是否始终位于顶部(在这种情况下是树中最新的),解决此问题的正确方法应该是创建多个导航器并决定使用哪个导航器来显示您的对话框,但这会使您的很多代码变得复杂!

在此处输入图像描述

于 2022-02-17T13:24:13.153 回答