how to update parent widget after showDialog is closed in Flutter? - flutter

I have a widget with an icon when I click on it a dialog widget is shown, here is the call for the dialog :
// this icon is in widget parent
IconButton(
icon: Icon(
Icons.info_outline,
size: mobileWidth * 0.07,
),
tooltip: 'information',
color: Colors.blueGrey,
onPressed: () {
showAlertInfo(context, code);
setState(() {});
},
),
here is my dialog :
showAlertInfo(BuildContext context, String code) {
showDialog(
context: context,
builder: (context) {
return StatefulBuilder(
builder: (context, setState) {
return AlertDialog(
title: Text(
"Information sur le client $code", ),
content: SingleChildScrollView(
child: Container( .....
/* ...
this dialog has some operations that changes info
values of the widget that called this in first place
it is a big code to put here*/
// here I have a close button
actions: [
FlatButton(
child: Text(
"Fermer",
style: TextStyle(
color: Colors.red,
fontSize: mobileWidth * 0.035,
fontWeight: FontWeight.bold,
),
),
onPressed: () {
Navigator.of(context).pop(); // dismiss dialog
},
),
],
);
what I'm trying to achieve is when the dialog is dismissed I want the parent widget to be updated, so how I call setState of the parent widget when the dialog widget is closed ?

For Async function
Add await before showDialog() and call setState((){}) on the next line.
await showDialog(
context: context,
builder: (context) {
return yourWidget;
}
);
setState((){});
For Sync Function
Use the .then() callback, and call setState((){}) in it.
showDialog(
context: context,
builder(context) {
return yourWidget;
}).then((_){
setState((){});
}
);

Related

Text widget doesn't appear in dialog after user Future.delayed in Flutter

I have a dialog that appears after user click on send button . When dialog appears , I want to show a text after 5 seconds . I use Future.delayed but the text doesn't appear at all . It appears only when I close the dialog and open it again . I want to show the text after 5 seconds from opening the dialog .
Here is my function
void _initialize() {
Future<void>.delayed(const Duration(seconds: 3), () {
if (mounted) {
setState(() {
visibility = true;
});
}
});
}
}
And here is my dialog code in the onTab of the button
_initialize()
showDialog(context: context,
barrierDismissible: false,
builder: (BuildContext contextd){
return WillPopScope(
onWillPop: () {return Future.value(false);},
child: Dialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10)
),
child: Padding(
padding: EdgeInsets.fromLTRB(20.w, 20.h, 20.w, 20.h),
child: Column(
children: [
//here are some widgets
Visibility(
visible:visibility?true:false,
child: Text("Resend?",style: TextStyle(decoration:
TextDecoration.underline,),)),
],),
),
),
);
});
Try using StatefulBuilder like this:
showDialog(
context: context,
builder: (BuildContext context) => StatefulBuilder(
builder: (context, setState) {
return //somthing to return;
},
));
This happens because your setState that update visibility has a different context than builder dialog. Visibility is actually update but only appear in dialog when close and open again because this is how build dialog is updated. If you want to work with the context dialog need to use that widget:
StatefulBuilder(
builder: (context, setState) {
Into your dialog and then call that setState.
Try using a StatefulBuilder. Using the bool visible and the setDialogState argument, you can update the state of the contents of the dialog.
showDialog(
context: context,
barrierDismissible: false,
builder: (BuildContext context) {
return StatefulBuilder(
builder(context, setDialogState) {
// this variable is used for the conditional display
bool visible = false;
// this future will update the visible variable in 3 seconds, after the dialog is displayed already
Future.delayed(Duration(seconds: 3)).then(() => setDialogState(() { visible = true;}));
return WillPopScope(
onWillPop: () { return Future.value(false); },
child: Dialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10)
),
child: Padding(
padding: EdgeInsets.fromLTRB(20.w, 20.h, 20.w, 20.h),
child: Column(
children: [
//here are some widgets
Visibility(
visible:visible,
child: Text(
"Resend?",
style: TextStyle(
decoration: TextDecoration.underline,
),
),
),
],
),
),
),
);
},
);
};

setstate for elevated button in dialog(Flutter)?

For the elevated button, I would like to show the visible/hide part content through setState. However, I could do it in normal pages but not a Dialog.
Here's the code:
bool addmaterial = true;
ClipRRect(
borderRadius: BorderRadius.circular(50),
child: SizedBox(
height: 40,
width: 400,
child: ElevatedButton(
style: ButtonStyle(
backgroundColor:
MaterialStateProperty.all<Color>(
Color(0xfff4f4f4)),
),
onPressed: () {
addmaterial = !addmaterial;
},
Try adding a StateFulBuilder inside your showDialog widget. If you want to change the state inside the showDialog
showDialog(
context: context,
builder: (BuildContext context) {
return StatefulBuilder(
builder: (context, setState) {
return AlertDialog(
actions: <Widget>[],
content: Container(),
);
},
);
},
);

How to dismiss alert dialog when clicked outside of it

I have an alert dialog that I want to be dismissed when clicked outside of it, I know this is the default behavior of alert dialogs in flutter, but I don't know what's the problem that's preventing it from closing when clicked outside.
I tried to use barrierDismissable to true, but still, it doens't work.
This is my dialog :
termsAndConditionsDialog(BuildContext context) {
AlertDialog alert = AlertDialog(
title: Text("Terms and Conditions", style: TextStyle(fontSize: 18, color: AppColors.accentColor),),
content: Text(
generalSettings.policyForCustomer,
style: TextStyle(fontSize: 16),
),
);
// show the dialog
showDialog(
barrierDismissible: true,
context: context,
builder: (BuildContext context) {
return alert;
},
);
}
and this is how I call it from button's onPressed :
termsAndConditionsDialog(context);
call this upon onPressed or onTap:
void showMessage(){
showDialog(
context:context,
builder: (Buildcontext context){
return AlertDialog(
backgroundColor: Colors.transparent,
content: Container(
width: MediaQuery.of(context).size.width,
height: 100,
alignment: AlignmentDirectional.center
child: Text("TRIAL",style: TextStyle(color: Colors.white))
)
)
}
)
}
Custom Alert method
typedef ResponseCallbackValueLess = void Function();
showAlertDialogWithOkButton(
BuildContext context,
String message,
String heading,
String buttonAcceptTitle,
ResponseCallbackValueLess callback) {
Widget continueButton = FlatButton(
child: Text(buttonAcceptTitle),
onPressed: () {
callback();
},
);
called like below:
showAlertDialogWithOkButton(context,
'No items found in your cart.',
"app name", "Ok", dismissAlert(context));
dismissAlert(context){
Navigator.pop(context);
}

How to use back option in flutter programmatically

I am calling a method and trying to go back after the transections is done. But the code doesn't work. Here is what I am trying,
onPressed: (){
_updateResult(context);
},
void _updateResult(BuildContext context) async{
// some api calls and checks goes here
Navigator.of(context).pop();
}
This is how I visit to a page
Navigator.push(context, SlideLeftRoute(page: EnterResult(item)));
I have a custom class SlideLeftRoute
class SlideLeftRoute extends PageRouteBuilder {
final Widget page;
SlideLeftRoute({this.page})
: super(
pageBuilder: (
BuildContext context,
Animation<double> animation,
Animation<double> secondaryAnimation,
) =>
page,
transitionsBuilder: (
BuildContext context,
Animation<double> animation,
Animation<double> secondaryAnimation,
Widget child,
) =>
SlideTransition(
position: Tween<Offset>(
begin: const Offset(1, 0),
end: Offset.zero,
).animate(animation),
child: child,
),
);
}
THE PROBLEM CODE
I have found which code creates problems. Here I was calling another method for showing dialogue. if I comment the code it works
void _showMsg(msg) {
// flutter defined function
showDialog(
context: context,
builder: (BuildContext context) {
// return object of type Dialog
return AlertDialog(
backgroundColor: Colors.grey[800],
content: new Text(msg,
style: TextStyle(
color: Colors.white,
fontSize: 14.0,
decoration: TextDecoration.none,
fontFamily: 'Lato',
fontWeight: FontWeight.normal,
),
),
//content: new Text("Alert Dialog body"),
actions: <Widget>[
// usually buttons at the bottom of the dialog
new FlatButton(
child: new Text("Close"),
onPressed: () {
Navigator.of(context).pop();
},
),
],
);
},
);
}
So here after the api call is done, it should go to the back screen but nothing happening.
Thank you.
The problem is because when you call Navigator.of(context).pop(); from the action of an alert AlertDialog, it will pop the presented dialog. You have to pop your screen again. For that you can use future returning by showDialog method.
That is change your _showMsg method like following.
Note the then(..)... on showDialog
void _showMsg(msg) async {
// flutter defined function
await showDialog(
context: context,
builder: (BuildContext localContext) {
// return object of type Dialog
return AlertDialog(
backgroundColor: Colors.grey[800],
content: new Text(
msg,
style: TextStyle(
color: Colors.white,
fontSize: 14.0,
decoration: TextDecoration.none,
fontFamily: 'Lato',
fontWeight: FontWeight.normal,
),
),
//content: new Text("Alert Dialog body"),
actions: <Widget>[
// usually buttons at the bottom of the dialog
new FlatButton(
child: new Text("Close"),
onPressed: () async {
print("poping");
Navigator.of(context).pop();
},
),
],
);
},
).then((value) {
print("poping from screen");
Navigator.of(context).pop();
});
}

show dialog when long pressed and pop it when finger up

I want to show a dialog when user long pressed on an item and pop it when finger up but it can't detect tap up.
I put dialog on another GestureDetector and use onTapUp property of it to pop dialog.
GestureDetector(
child: studentIcon(index, context),
onLongPress: () {
showDialog(
context: context,
builder: (context) {
return GestureDetector(
onTapUp: (detail) {
Navigator.pop(context);
},
child: DialogDetail(
index: index,
),
);
});
},
I expect to pop dialog after finger up after long pressed.
You can't do that as there is an context problem in GestureDetector.
Please follow this answer to implement this thing.
Try to make method to open dialog . i provide alert dialog code..
void _showText(BuildContext context) {
showDialog(
context: context,
barrierDismissible: false,
builder: (context) {
return AlertDialog(
content: Text(
"User name :${nameEditText.text} \nPassword : ${passwordEditText.text}"),
actions: <Widget>[
new FlatButton(
onPressed: () {
Navigator.of(context).pop();
},
child: new Text("OK"))
],
);
});
}
}
after that called on button click..
child: RaisedButton(
padding: EdgeInsets.all(15.0),
onPressed: () {
_showText(context);
},
child: Text(
"Submit",
style: TextStyle(fontSize: 15, color: Colors.white),
),
color: Colors.blue,
),