I have a Update Button by clicking on which data loads in background.
When the data loads I am displaying AlertDialog which closes automatically when the data gets loaded.
However while the data is loading and if the user clicks somewhere else on screen the Dialog Box closes which is undesirable.
The question is How can I prevent DialogBox to close?
Future<void> _loadingDialog(String title) async {
return showDialog(
context: context,
barrierDismissible: true,
builder: (context) {
return AlertDialog(
title: Text(title),
content: LinearProgressIndicator(
backgroundColor: colorPrimaryLight,
valueColor: AlwaysStoppedAnimation<Color>(colorPrimaryDark),
),
);
},
);
}
Okay it was simple I just had to set
barrierDismissible: false,
Related
I am trying to make an API call using FutureBuilder in flutter but it seems like the request is not sent because I do not see the response printing. here is my future builder:
FutureBuilder(
future: authBloc.login(user, pass),
builder: (context, AsyncSnapshot snapshotItem) {
Map<String, dynamic> data = snapshotItem.data[0];
print(data['response']);
if (data.containsKey('id')) {
saveId(data['id']);
Navigator.of(context).pushReplacement(
MaterialPageRoute(
builder: (BuildContext context) {
return MainPage();
}));
}
if (data.containsKey("response")) {
if (data['response'] == false) {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text('An Error Has Occurred'),
content: Text(
'Please Make Sure That You Are Entering Valid UserName And Password'),
actions: <Widget>[
FlatButton(
child: Text("OK"),
onPressed: () =>
Navigator.of(context).pop(),
)
],
);
});
}
}
},
);
the authBloc.login(user, pass), part is login function in another file that makes the API call and I thought it is not necessary to include that file here.
Although I can't see the rest of your code, I think what you are trying to achieve should be done with an method and not a widget. When the user presses submit, call a function that basically contains what you wrote on that builder.
Calling navigator from within the builder is a bad idea. Any builder is expected to be called multiple times and in your case will lead to unexpected behaviour, that might be what you are seeing
How do I add Progressbar?
After click button, I need to display a progress bar while executing the task and after complete task, the dialog should be dismissed and move to next page if successful login.
in Raised Button:
onPressed: () async {
(isOffline)
? showSnackBar(context)
: checkingValidation(usernameController, context, _url);
}
checkingValidation(TextEditingController usernameController, BuildContext context, String _url) async {
if(....){
...
}else{
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => HomePage()))
}
You should use Stack and inside that use alert dialog as you want.
Add a flag like bool showProgress, whenever you need a progress alert dialog to be shown or hide just set showProgress=true or showProgress=false respectively in setState to show or hide the alert dialog widget.
or simply use this template I created.
static showProgressDialog(BuildContext context, String title) {
try {
showDialog(
context: context,
barrierDismissible: false,
builder: (context) {
return AlertDialog(
content: Flex(
direction: Axis.horizontal,
children: <Widget>[
CircularProgressIndicator(),
Padding(padding: EdgeInsets.only(left: 15),),
Flexible(
flex: 8,
child: Text(
title,
style: TextStyle(
fontSize: 16, fontWeight: FontWeight.bold),
)),
],
),
);
});
} catch (e) {
print(e.toString());
}
}
when you want to show this just call
AppUtils.showProgressDialog(context, "Please wait");
when you have done task, just call Navigator.pop(context);
You can create a class as AppUtils and place this template in class, so you can reuse this anywhere in your app.
This question already has an answer here:
How To Override the “Back” button in Flutter? [duplicate]
(1 answer)
Closed 4 years ago.
I have an app that needs move from screen 1 to screen two ....now when the user presses the back button..it should show a dialog box...if the user presses yes it has to exit...any help?the upper solutions don't work
It seems like you can use WillPopScope. You also need to pass a callback function which will indicate what will happen on pressing the back button.
In your case, you can add the code to show an AlertDialog which will ask for exit confirmation from the user.
You can simply wrap your Scaffold inside a WillPopScope.
Example:
Widget build(BuildContext context) {
return WillPopScope(
child: /*Your scaffold widget*/
onWillPop: () {
return showDialog(
context: context,
barrierDismissible: false,
builder: (BuildContext context) {
return AlertDialog(
title: Text("Confirm Exit"),
content: Text("Are you sure you want to exit?"),
actions: <Widget>[
FlatButton(
child: Text("YES"),
onPressed: () {
SystemNavigator.pop();
},
),
FlatButton(
child: Text("NO"),
onPressed: () {
Navigator.of(context).pop();
},
)
],
);
}
);
return Future.value(true);
},
I have problem with showDialog, when i press nothing happens but if i use Navigator.pushNamed(context, "/screen1") it works. I can not run Navigator.pop(context), it does not return any errors.
_showDialog(BuildContext context) {
return showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: new Text("Alert Dialog title"),
actions: <Widget>[
new FlatButton(
child: new Text("Back"),
onPressed: () {
//Navigator.pushNamed(context, "/screen1");
Navigator.pop(context);
},
),
],
);
});}
In my build() :
IconButton(
iconSize: 30.0,
onPressed: () => _showDialog(context),
icon: Icon(
Icons.clear,
color: Colors.white,
),
)
had the same issue .having useRootNavigator: false, in showDialog params solved my issue .
Use pop() two times:-
Navigator.of(context).pop();
Navigator.of(context).pop();
Reason: first pop function dismiss the dialog and Second pop function close the screen
The above answer should be accepted for this question, just elaborating the above answer
return showDialog(
context: context,
useRootNavigator: false, //this property needs to be added
builder: (BuildContext context) {....});
Try calling Navigator.of(context).pop(); instead of Navigator.pop(context);
For closing dialogs, you can also use:
Navigator.pop(context, true);
Source: https://docs.flutter.io/flutter/widgets/Navigator/pop.html
For those who have nested/multiple Navigators, you can also use the pop method as shown below (notice the named parameter rootNavigator set to true):
Navigator.of(context, rootNavigator: true).pop();
As suggested by others, I tried setting the useRootNavigator in the showDialog as false but this way the barrierColor wasn't covering the whole screen (it was only covering the screen displayed by Navigator object the dialog was in).
In summary, you can use the way showed above if you have nested navigators and want to achieve having the barrierColor covering the whole screen.
While dismissing a presented Cupertino alert dialogue action using the explained method my entire screen gets popped of and the alert dialogue stays on the screen. This is my code.
if (deviceList.isEmpty){
var alert = new CupertinoAlertDialog(
title: new Text("Alert"),
content: new Text("There was an error signing in. Please try again."),
actions: <Widget>[
new CupertinoDialogAction(
child: const Text('Discard'),
isDestructiveAction: true,
onPressed: () { Navigator.pop(context, 'Discard'); }
),
new CupertinoDialogAction(
child: const Text('Cancel'),
isDefaultAction: true,
onPressed: () { Navigator.pop(context, 'Cancel'); }
),
],
);
showDialog(context: context, child: alert);
}
Is there anything wrong in what I am doing? I cant find any other solution to dismiss the alert dialogue. Please help.
In this case, you need to specify the rootNavigator to of() :
Navigator.of(context, rootNavigator: true).pop("Discard");
Check the implementation proposed in the documentation