Reputation: 12612
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
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
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
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
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 justNavigator.pop(context, result)
.
so I'd assume one of these two should do what you want.
Upvotes: 173
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
Reputation: 4254
This will close the dialog/alert box.
Navigator.of(context).pop();
Upvotes: 4
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
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
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
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
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
Reputation: 269
//it work conrrectly
onPressed: () {
Navigator.of(context, rootNavigator: true).pop();
},
Upvotes: 22
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
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