Ammy Kang
Ammy Kang

Reputation: 12612

How to dismiss flutter dialog?

I am new to flutter, I want to dismiss my dialog after the task completion. I've tried with:

Navigator.pop(context, true); 

But my screen is getting black and dialog is still up there. here is my dialog code.

Dialog _dialog = new Dialog(
  child: new Row(
    mainAxisSize: MainAsixSize.min, 
    children: <Widget> [
    new CircularProgressIndicator(), 
    new Text("Loading")]),     

); 

Upvotes: 144

Views: 189823

Answers (14)

Maysam R
Maysam R

Reputation: 969

 static Future<BuildContext?> wait(BuildContext context, String title) async {
   BuildContext? dialogContext;
   showDialog(
     context: context,
     builder: (BuildContext context) {
       dialogContext = context;
       return AlertDialog(
          backgroundColor: MyColors.color_primary_dark(),
          surfaceTintColor: MyColors.color_primary_dark(),
          shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(20.0))),
          contentPadding: EdgeInsets.all(20),
          content: StatefulBuilder(builder: (BuildContext context, StateSetter setStatePopupMain) {
            return Column(mainAxisSize: MainAxisSize.min, children: [
              CircularProgressIndicator(strokeWidth: 2, color: MyColors.color_attention()),
              SizedBox(height: 20),
              MyText(title, color: MyColors.text_always_white()),
            ]);
          }));
    });
  await Future.delayed(const Duration(milliseconds: 100));
  return dialogContext;}

and use like this:

BuildContext? dialogContext= await  wait(context,"Loding...");
// do heveay work
Navigator.pop(dialogContext);

Upvotes: 0

M Karimi
M Karimi

Reputation: 3583

You can use _dialogContext to handle closing the dialog, just you should check some conditions before calling pop() (_dialogContext != null && _dialogContext!.mounted).

    BuildContext? _dialogContext;    
    
    showDialog<void>(
                      context: context,
                      builder: (ctx) {
                        _dialogContext = ctx;
                        return AlertDialog(content: child);
                      },
                    );
    
    
    //close dialog
     if (_dialogContext != null && _dialogContext!.mounted) {
          Navigator.pop(_dialogContext!);
        }

Upvotes: 2

c.lamont.dev
c.lamont.dev

Reputation: 767

Expanding on the answer from @live-long, you can create a class to handle the showing and dismissing of the dialog.

Example:

class ProcessingDialog {
  ProcessingDialog({
    required this.context,
    required this.child,
  });
  final BuildContext context;
  final Widget child;
  BuildContext? dialogContext;

  void showProcessingDialog() {
    if (dialogContext != null && dialogContext!.mounted) {
      Navigator.pop(dialogContext!);
    }
    if (!context.mounted) {
      return;
    }
    showDialog(
      context: context,
      barrierDismissible: false,
      builder: (ctx) {
        dialogContext = ctx;
        return AlertDialog(content: child);
      },
    );
  }

  void dismissProcessingDialog() {
    if (dialogContext != null && dialogContext!.mounted) {
      Navigator.pop(dialogContext!);
    }
  }
}

Then you can use it like so:

final processingDialog =
    ProcessingDialog(context: context, child: const Text('Processing...'));
processingDialog.showProcessingDialog();
await Future.delayed(const Duration(seconds: 5));
processingDialog.dismissProcessingDialog();

Upvotes: 1

G&#252;nter Z&#246;chbauer
G&#252;nter Z&#246;chbauer

Reputation: 658057

https://api.flutter.dev/flutter/material/showDialog.html says

The dialog route created by this method is pushed to the root navigator. If the application has multiple Navigator objects, it may be necessary to call Navigator.of(context, rootNavigator: true).pop(result) to close the dialog rather just Navigator.pop(context, result).

so I'd assume one of these two should do what you want.

Upvotes: 173

imalixch
imalixch

Reputation: 53

In 2023 here is the latest way to do that. Because in my case Navigator.of(context).pop(); didn't work

Navigator.of(context, rootNavigator: true).pop();

Upvotes: 5

Krishnamoorthy Acharya
Krishnamoorthy Acharya

Reputation: 4254

This will close the dialog/alert box.

Navigator.of(context).pop();

Upvotes: 4

Waqar Ahmed
Waqar Ahmed

Reputation: 399

Try this. It will definitely work. use the context of pageBuilder in Navigator to pop the dialog from screen.

showGeneralDialog(
     context: context,
     barrierLabel: "XYZ",
     barrierDismissible: true,
     barrierColor: Colors.black.withOpacity(0.7),
     pageBuilder: (dialogContext, __, ___) {
       return Center(
        child: Container(
          height: 240,
          margin: const EdgeInsets.symmetric(horizontal: 15),
          decoration: bd,
          child: SizedBox.expand(
              GestureDetector(
                   onTap: (){
                       Navigator.pop(dialogContext);
                    },
                    child: const Padding(
                       padding: EdgeInsets.fromLTRB(10,0,10,0),
                       child: Icon(Icons.close, size: 26, color:Colors.white),
                     ),
               ),
           )
         ) 
       );
     }
  );

 

Upvotes: 2

Jeff
Jeff

Reputation: 475

Add on to Günter's answers. If you need to dismiss it when the user clicks elsewhere change this property to true

barrierDismissible: true,

Upvotes: 2

Dhairya Lakhera
Dhairya Lakhera

Reputation: 4808

showDialog(
  context: context,
  builder: (BuildContext context) => Center(
    child: CircularProgressIndicator(),
  ),
);

await Future<int>.delayed(Duration(seconds: 3));

Navigator.of(context, rootNavigator: true).pop();

Upvotes: 2

Mihail Ya
Mihail Ya

Reputation: 471

Better to use Completer, because if your operation is too short or the device is too slow, then the dialogContext variable will not be initialized and you can't close the dialog.

final dialogContextCompleter = Completer<BuildContext>();
showDialog<void>(
  context: context,
  barrierDismissible: false,
  builder: (BuildContext dialogContext) {
    if(!dialogContextCompleter.isCompleted) {
      dialogContextCompleter.complete(dialogContext);
    }
    return AlertDialog(
      content: CircularProgressIndicator(),
    );
  },
);

// Close progress dialog
final dialogContext = await dialogContextCompleter.future;
Navigator.pop(dialogContext);

Upvotes: 12

Vicky Salunkhe
Vicky Salunkhe

Reputation: 11025

Generally Navigator.pop(context); works.

But If the application has multiple Navigator objects and dialogBox doesn't close, then try this

Navigator.of(context, rootNavigator: true).pop();

If you want to pass result call, try

Navigator.pop(context,result);

OR

Navigator.of(context, rootNavigator: true).pop(result);

Upvotes: 14

Wai Yan Moung
Wai Yan Moung

Reputation: 269

//it work conrrectly
onPressed: () {
   Navigator.of(context, rootNavigator: true).pop();
},

Upvotes: 22

live-love
live-love

Reputation: 52494

This code works for me:

  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);

Upvotes: 93

CopsOnRoad
CopsOnRoad

Reputation: 268424

If you don't want to return any result after showDialog is closed, you can use

Navigator.pop(context);

If you want to pass result call

Navigator.pop(context, result);

Example:

showDialog(
    context: context,
    builder: (_) {
      return AlertDialog(
        title: Text('Wanna Exit?'),
        actions: [
          FlatButton(
            onPressed: () => Navigator.pop(context, false), // passing false
            child: Text('No'),
          ),
          FlatButton(
            onPressed: () => Navigator.pop(context, true), // passing true
            child: Text('Yes'),
          ),
        ],
      );
    }).then((exit) {
  if (exit == null) return;

  if (exit) {
    // user pressed Yes button
  } else {
    // user pressed No button
  }
});

Upvotes: 37

Related Questions