Here is my _showDialog function:
Future<void> _showDialog({BuildContext context, String msg, String title}) async {
showDialog<bool>(
context: context,
builder: (context) {
return AlertDialog(
title: Text(title),
content: Text(msg),
actions: [
FlatButton(
child: Text('Ok'),
onPressed: () => Navigator.of(context).pop(true),
),
],
);
});
}
Here is my code:
if (result.contains("Error")) {
// Error!!!
// Show ERROR dialog box.
_showDialog(context: context, title: "Error", msg: result);
} else {
// Success!!!
// Show SUCCESS dialog box, then return to the previous screen.
_showDialog(context: context, title: "Success", msg: "Success!");
Navigator.pop(context); // return to the previous screen
}
If error occurs the ERROR dialog box it shows.
But if there is no error the SUCCESS dialog box it not show.
If the line
Navigator.pop(context);
is commented out the SUCCESS dialog box it show.
I need to show the SUCCESS dialog box before return to the previous screen.
You should then await the close button response on your dialog, like:
Future _showDialog({BuildContext context, String msg, String title}) async {
return await showDialog<bool>(
context: context,
builder: (context) {
return AlertDialog(
title: Text(title),
content: Text(msg),
actions: [
FlatButton(
child: Text('Ok'),
onPressed: () => Navigator.of(context).pop(true),
),
],
);
});
}
and then
if (result.contains("Error")) {
// Error!!!
// Show ERROR dialog box.
_showDialog(context: context, title: "Error", msg: result);
} else {
// Success!!!
// Show SUCCESS dialog box, then return to the previous screen.
await _showDialog(context: context, title: "Success", msg: "Success!");
Navigator.pop(context); // return to the previous screen
}
I was also having the same issue but adding await in front of showDialog fixed it for me
you should await the showDialog like this
Future<void> authSuccessHandle(
{required String title,
required String subtitle,
required BuildContext context}) async {
await showDialog(
context: context,
builder: (BuildContext ctx) {
return AlertDialog(
backgroundColor: Colors.green.shade50,
title: Row(
children: [
Padding(
padding: const EdgeInsets.only(right: 6.0),
child: CircleAvatar(
backgroundColor: ColorsConsts.AppMainColor,
child: const Icon(
Icons.done,
color: Colors.white,
size: 25,
),
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
title,
style: const TextStyle(
fontSize: 16,
),
),
),
],
),
content: Text(
subtitle,
style: const TextStyle(
fontSize: 14,
),
),
actions: [
TextButton(
onPressed: () {
Navigator.pop(context);
},
child: Text(
'Ok',
style: TextStyle(
color: ColorsConsts.AppMainColor,
fontSize: 16,
),
),
)
],
);
});
}
Related
How can I to close all the showDialogs in my aplication? in this case _mostrarDialogConfirmacion is the dialog where i request to the user a confirmation to make a query, cargandoDialog is another dialog where i show a loading message while the query is executing, when the query finish, i want to close the two dialogs and only see the _mostrarDialogMensaje dialog
_mostrarDialogConfirmacion(
mensaje,
BuildContext context,
codLink,
motivo,
) {
return showDialog(
context: context,
builder: (context){
return AlertDialog(
title: const Text(
'Informacion',
textAlign: TextAlign.center,
),
content: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget> [
Text(mensaje, textAlign: TextAlign.center),
],
),
actions: <Widget> [
TextButton(
onPressed: () async {
Navigator.of(context).pop();
cargandoDialog(context);
List<dynamic> ingresarReclamo1 = await ingresarReclamo
.ingresarReclamo(codLink, titular, motivo);
// ignore: use_build_context_synchronously
Navigator.of(context).pop();
// ignore: use_build_context_synchronously
_mostrarDialogMensaje(
ingresarReclamo1[0].observaciones,
ingresarReclamo1[0].validado,
context,
);
},
child: const Text('Si')
),
TextButton(
onPressed: ()=> Navigator.of(context).pop(),
child: const Text('No')
),
],
);
}
);
}
you will dismiss first dialog and then you can use whenComplete to dismiss the second dialog
showDialog(
.....
).whenComplete(() => Navigator.of(context).pop())
You can return bool while .pop(boolValue) to check the tap button. Also, the showDialog is a future method, you can use await until it finished and then processed to next dialog. Navigator.of(context).pop() will be used to close recent dialog on this case. As for my understanding about the question, try this example code.
_mostrarDialogConfirmacion(mensaje, BuildContext context, codLink, motivo) {
return showDialog(
context: context,
barrierDismissible: false,
builder: (context) {
return AlertDialog(
title: const Text('Informacion', textAlign: TextAlign.center),
content: Column(
mainAxisSize: MainAxisSize.min,
),
actions: <Widget>[
TextButton(
onPressed: () async {
// Navigator.of(context)
// .pop(); //if you like to close previous one before showing the next dialog
final bool isSi = await showDialog(
barrierDismissible: false,
builder: (context) => AlertDialog(
content: Text("Second Dialog"),
actions: [
TextButton(
onPressed: () {
Navigator.of(context).pop(true);
},
child: const Text('Si')),
TextButton(
onPressed: () =>
Navigator.of(context).pop(false),
child: const Text('No')),
],
),
context: context);
if (mounted && isSi) {
Navigator.of(context).pop();
await showDialog(
builder: (context) => AlertDialog(
content: Text("_mostrarDialogMensaje")),
context: context);
}
},
child: const Text('Si')),
TextButton(
onPressed: () => Navigator.of(context).pop(),
child: const Text('No')),
],
);
});
}
So I am facing this problem that my alert Dialog isn't displaying. I had tried every possible solution and searching here and there but nothing works. When I click on the edit button from the pop up menu nothing is displayed everything remains the same.
Calling alert Dialog
trailing: PopupMenuButton(
icon: Icon(Icons.more_vert),
itemBuilder: (context)=>[
PopupMenuItem(
value:1,
onTap: (){
//debugPrint('popup');
Navigator.pop(context);
_showMyDialog();
},
child: ListTile(
leading: Icon(Icons.edit),
title: Text('Edit'),
)),
PopupMenuItem(
value:1,
// onTap: (){
// Navigator.pop(context);
// showDialogBox();
// },
child: ListTile(
leading: Icon(Icons.delete),
title: Text('Delete'),
)),
]),
Alert Dialog Code
Future<void> showDialogBox(String title)async{
editController.text=title;
debugPrint('dialog');
return showDialog<void>(
context: context,
barrierDismissible: false,
builder: (BuildContext context){
debugPrint('alert');
return AlertDialog(
title: Text('Update'),
content: Container(
child: TextFormField(
controller: editController,
),
),
actions: [
TextButton(onPressed: (){
Navigator.pop(context);
}, child: Text('Update')),
TextButton(onPressed: (){
Navigator.pop(context);
}, child: Text('Cancel')),
],
);
}
);
}
Complete Class Code
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_database/ui/firebase_animated_list.dart';
import 'package:firebase_tutorial/utils/routes/routes_names.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:firebase_database/firebase_database.dart';
import '../../utils/utils.dart';
class PostScreen extends StatefulWidget {
const PostScreen({Key? key}) : super(key: key);
#override
State<PostScreen> createState() => _PostScreenState();
}
class _PostScreenState extends State<PostScreen> {
final ref=FirebaseDatabase.instance.ref('Post');
FirebaseAuth _auth=FirebaseAuth.instance;
final searchController=TextEditingController();
final editController=TextEditingController();
#override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: ()async{
SystemNavigator.pop();
return true;
},
child: Scaffold(
appBar: AppBar(
automaticallyImplyLeading: false,
title: Text('Post Screen'),
actions: [
GestureDetector(
onTap: (){
_auth.signOut().then((value){
Navigator.pushNamed(context, RoutesNames.loginScreen);
}).onError((error, stackTrace){
Utils().toastMessage(error.toString());
});
},
child: Icon(Icons.logout_outlined)),
SizedBox(width: 10,),
],
),
floatingActionButton: FloatingActionButton(
onPressed:(){
Navigator.pushNamed(context, RoutesNames.newPost);
},
child: Icon(Icons.add),),
body: Column(
children: [
// Expanded(
// child:FirebaseAnimatedList(
// query: ref,
// itemBuilder: (context,snapshot,animation,index){
// return ListTile(
// title: Text(snapshot.child('post').value.toString()),
// );
// }
// ),
// ),
Padding(
padding: const EdgeInsets.all(10.0),
child: TextFormField(
onChanged: (String value){
setState(() {
});
},
controller: searchController,
decoration: InputDecoration(
border: OutlineInputBorder(),
hintText: "Search",
),
),
),
Expanded(child: StreamBuilder(
stream: ref.onValue,
builder: (context,AsyncSnapshot<DatabaseEvent> snapshot){
if(!snapshot.hasData){
return CircularProgressIndicator();
}
else{
return ListView.builder(
itemCount: snapshot.data!.snapshot.children.length,
itemBuilder: (context,index){
Map<dynamic,dynamic> map=snapshot.data!.snapshot.value as dynamic;
List<dynamic> list=[];
list.clear();
list=map.values.toList();
final title=list[index]['post'].toString();
if(searchController.text.isEmpty){
return ListTile(
title: Text(list[index]['post']),
subtitle: Text(list[index]['id'].toString()),
trailing: PopupMenuButton(
icon: Icon(Icons.more_vert),
itemBuilder: (context)=>[
PopupMenuItem(
value:1,
onTap: (){
//debugPrint('popup');
Navigator.pop(context);
_showMyDialog();
},
child: ListTile(
leading: Icon(Icons.edit),
title: Text('Edit'),
)),
PopupMenuItem(
value:1,
// onTap: (){
// Navigator.pop(context);
// showDialogBox();
// },
child: ListTile(
leading: Icon(Icons.delete),
title: Text('Delete'),
)),
]),
);
}
else if(title.toLowerCase().contains(searchController.text.toLowerCase())){
return ListTile(
title: Text(list[index]['post']),
subtitle: Text(list[index]['id'].toString()),
);
}
else{
return Container();
}
});
}
}))
],
),
),
);
}
Future<void> showDialogBox(String title)async{
editController.text=title;
debugPrint('dialog');
return showDialog<void>(
context: context,
barrierDismissible: false,
builder: (BuildContext context){
debugPrint('alert');
return AlertDialog(
title: Text('Update'),
content: Container(
child: TextFormField(
controller: editController,
),
),
actions: [
TextButton(onPressed: (){
Navigator.pop(context);
}, child: Text('Update')),
TextButton(onPressed: (){
Navigator.pop(context);
}, child: Text('Cancel')),
],
);
}
);
}
}
try adding a delay before calling showDialog like this:
await Future.delayed(const Duration(milliseconds: 10));
Your dialog isnt displayed because when you select a menu item the pop() method is automatically called to close the popup menu; so if you open a dialog immediately, the dialog will get automatically popped.
hope this fixes your issue
I have a pop-up that asks whether to exit the application or not, it worked correctly. But after updating the SDK version, an error occurred:
"A value of type 'Object' can't be returned from the method '_onBackPressed' because it has a return type of 'Future'"
I will be grateful for your help
My code:
Future<bool> _onBackPressed() {
return showDialog(
context: context,
builder: (context) => new AlertDialog(
title: new Text('You want to exit the application?'),
content: new Text('You want to exit the application',
style: TextStyle(
fontSize: 20,
),
),
actions: <Widget>[
new GestureDetector(
onTap: () => Navigator.of(context).pop(false),
child:
Text("No",
style: TextStyle(
fontSize: 25,
),
),
),
SizedBox(height: 40),
new GestureDetector(
onTap: () => Navigator.of(context).pop(true),
child: Text("Yes",
style: TextStyle(
fontSize: 25,
),
),
),
],
),
) ??
false;
}
Image with errore:
Try this, and showDialog returns Future.
Future<bool> _onBackPressed() async {
return await showDialog(
context: context,
builder: (context) =>
I want to remove an entry from listview and db at the same time using swipe like this:
onPressed: () {
// Delete the item from DB
setState(() {
data.indexOf(data[index]);
data.removeAt(index);
});
Navigator.of(context).pop();
},
the methode doesn't seem to be working also i want help with how can I trigger the update on this page without the user to reopen the page.
return ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (context, index) {
List<Ia> data = snapshot.data;
print(data);
return Dismissible(
background: slideRightBackground(),
secondaryBackground: slideLeftBackground(),
key: Key(data[index].toString()),
// ignore: missing_return
confirmDismiss: (direction) async {
if (direction == DismissDirection.endToStart) {
final bool res = await showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
content: Text(
"Are you sure you want to delete ` ${data[index]}?"),`
actions: <Widget>[
// ignore: deprecated_member_use
FlatButton(
child: Text(
"Cancel",
style:
TextStyle(color: Colors.black),
),
onPressed: () {
Navigator.of(context).pop();
},
),
FlatButton(
child: Text(
"Delete",
style: TextStyle(color: Colors.red),
),
onPressed: () {
// Delete the item from DB
setState(() {
data.indexOf(data[index]);
data.removeAt(index);
});
Navigator.of(context).pop();
},
),
],
);
});
return res;
} else {
// Navigate to edit page;
}
},
child: Card(
child: ListTile(
title: Text(data[index].name,
style: TextStyle(fontSize: 16)),
subtitle: Row(
children: [
Text(
"Status",
style: TextStyle(
fontSize: 12,
fontWeight: FontWeight.bold),
),
SizedBox(
width: 5,
),
Text(
data[index].state,
style: TextStyle(
color: Colors.lightBlue,
fontSize: 12,
),
),
],
),
),
),
);
});
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Right now you're only removing it from the list, which is pointless as the stream is from the database. You need to remove it from the database only.
In your onPressed(), remove setState() and add this :
await _fireStoreInstance.runTransaction(
(Transaction transaction) async {
transaction.delete(YOUR_DOC_REF_HERE); // i'd assume data[index].reference
},
Calling API in dismiss should be working,if you are using api to delete data from server database you need to call a delete function
Sample UI Code
class MyAppState extends State<MyApp> {
final items = List<String>.generate(20, (i) => 'Item ${i + 1}');
#override
Widget build(BuildContext context) {
final title = 'Dismissing Items';
return MaterialApp(
title: title,
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Scaffold(
appBar: AppBar(
title: Text(title),
),
body: ListView.builder(
itemCount: items.length,
itemBuilder: (context, index) {
final item = items[index];
return Dismissible(
key: Key(item),
// what to do after an item has been swiped away.
onDismissed: (direction) {
// Remove the item from the data source.
setState(() {
Deletedata(pass your id here);
items.removeAt(index);
});
// Then show a snackbar.
ScaffoldMessenger.of(context)
.showSnackBar(SnackBar(content: Text('$item deleted')));
},
// Show a red background as the item is swiped away.
background: Container(color: Colors.red),
child: ListTile(title: Text('$item')),
);
},
),
),
);
}
}
Delete function
Future<void> Deletedata(String id) async{
var response = await http.delete(Uri.parse("http://xxx.xx.xx.xx/api/delete_route/$id"), headers: {'Content-Type': 'application/json;charset=UTF-8', 'Charset': 'utf-8', 'Authorization': 'token',},);
print('Response status: ${response.statusCode}');
print('Response body: ${response.body}');
}
I have a small popup with a button "DELETE", however I want to change the text to "SELL" everytime the input text is different than 0.00
showDialog(
context: context,
builder: (context) {
String _popUpDeleteSoldText = "Delete";
return AlertDialog(
title: Text("Delete " + doc['propertyName'] + "?"),
content: Container(
height: 120,
child: Column(
children: <Widget>[
TextField(
onChanged: (text) {
if (text != "0.00") {
print("i'm != 0.00");
setState(() {
//TODO - THIS AIN'T WORKING
_popUpDeleteSoldText = "Sell";
});
} else {
print("i'm still 0");
setState(() {
_popUpDeleteSoldText = "Delete";
});
}
},
the button:
MaterialButton(
elevation: 4.0,
child: Text(
_popUpDeleteSoldText,
style: TextStyle(color: Colors.white),
)
....
The print are working on the onChange function, but the button text always say "Delete"
I would suggest to extract your AlertDialog into a separate StatefulWidget and then it will work.
You can wrap with StatefulBuilder directly like the following example
String contentText will change after use setState
showDialog(
context: context,
builder: (context) {
String contentText = "Content of Dialog";
return StatefulBuilder(
builder: (context, setState) {
return AlertDialog(
title: Text("Title of Dialog"),
content: Text(contentText),
actions: <Widget>[
FlatButton(
onPressed: () => Navigator.pop(context),
child: Text("Cancel"),
),
FlatButton(
onPressed: () {
setState(() {
contentText = "Changed Content of Dialog";
});
},
child: Text("Change"),
),
],
);
},
);
},
);