I have a request to the server, when I use FutureBuilder, the ConnectionState.waiting section, I want to use a custom dialog, but after ConnectionState.done, this dialog does not close, it does not even do Navigator.pop(context).
enter image description here
enter image description here
Try this
Before ConnectionState.waiting just call this onLoading(context);
then
if(ConnectionState. done){
Navigator.pop();
}
void onLoading(BuildContext context) {
showDialog(
context: context,
barrierDismissible: false,
builder: (BuildContext context) {
return Center(child: CircularProgressIndicator(color: Colors.blue));
});
}
Unfortunately, it is not possible to disable Alert Dialog using object orientation, and I designed dialogs on a separate page, and Navigator.pop() does not work, but with this method, I achieved my desired result.
FutureBuilder(
future: _futureEditName,
builder: (context,snapshot){
if(snapshot.connectionState == ConnectionState.waiting){
ShowWaitingDialog(context,true);
}else if(snapshot.connectionState == ConnectionState.done && snapshot.hasData){
ShowWaitingDialog(context,false)
}
}
);
show and dismiss Alert Dialog
ShowWaitingDialog(BuildContext context,bool show) {
showDialog(
context: context,
builder: (context) {
return show == true ?
AlertDialog(
insetPadding: const EdgeInsets.all(20),
alignment: Alignment.center,
title: Container(
width: double.maxFinite,
child: Column(
textDirection: TextDirection.rtl,
children: [
Row(
textDirection: TextDirection.rtl,
children: [
const SpinKitCircle(
color: Colors.lightBlue,
size: 35,
),
const SizedBox(width: 20,),
Container(
alignment: Alignment.center,
child: const Text(
'please wait',
style: TextStyle(
color: kGraydark,
fontSize: 15,
),
),
),
],
),
],
),
),
)
: FutureBuilder(builder: (context, snapshot) {
Navigator.of(context).pop();
Navigator.of(context).pop();
return Container();
},);
},);
}
Navigator.of(context).pop() It must be called twice
Related
I am working on an attendance application where I assign wages to the workers. I want to store all the wages given to the workers into the database. But the problem is I want to access all the given values on button click. I have no idea how it can be done in flutter. I am a beginner.
I have given all the codes and the image of what output i want.
Image of Emulator
Here is my code...
ATTENDANCE SCREEN
...rest code...
floatingActionButton: FloatingActionButton(
onPressed: () {
showDialog(
context: context,
barrierDismissible: false, // user must tap button!
builder: (BuildContext context) {
return AlertDialog(
title: const Text('Upload Patti'),
content: SingleChildScrollView(
child: ListBody(
children: [
TextFormField(
controller: _mainWagesController,
decoration: const InputDecoration(
border: OutlineInputBorder(),
hintText: "Enter Amount",
prefixIcon: Icon(Icons.wallet, color: Colors.blue),
),
),
],
),
),
actions: <Widget>[
ElevatedButton(
onPressed: () {
Navigator.pop(context);
newWages = _mainWagesController.text;
setState(() {});
},
child: const Text("Assign Wages"),
),
],
);
},
);
},
child: const Icon(Icons.check_circle),
),
body: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.all(8.00),
child: Column(children: [
const SizedBox(
height: 20,
),
Center(
child: Text(
"Date : ${DateFormat.yMMMEd().format(DateTime.parse(widget.attendanceDate.toString()))}",
style: const TextStyle(fontSize: 20),
),
),
const SizedBox(
height: 20,
),
FutureBuilder(
future: SupervisorAttendanceServices.getAttendancesDetailsList(
widget.attendanceId),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.hasData) {
var data = snapshot.data['hamal'];
return ListView.builder(
itemCount: data.length,
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemBuilder: (BuildContext context, int index) {
return HamalAttendanceWidget(
workerId: data[index]['worker_id'],
name: data[index]['worker_name'],
wages: newWages,
masterAttendanceId: widget.attendanceId,
isPrensent: data[index]
['attendance_worker_presense']
.toString());
});
} else if (snapshot.hasError) {
return const Center(
child: Text("Something went wrong !"),
);
} else {
return const Center(child: LinearProgressIndicator());
}
},
),
]),
),
),
...rest code
widget
Widget build(BuildContext context) {
return Card(
child: Column(children: [
Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.start,
children: [
const SizedBox(
width: 10,
height: 50,
),
const Icon(FeatherIcons.user),
const SizedBox(
width: 20,
),
Text(
widget.name,
style: const TextStyle(fontSize: 18),
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
SizedBox(
width: 150,
height: 60,
child: TextFormField(
// onChanged: _onChangeHandler,
initialValue: widget.wages.toString(),
decoration: const InputDecoration(
hintText: "Wages",
prefixIcon: Icon(
Icons.wallet,
color: Colors.blue,
)),
)),
],
)
]),
);
}
I suggest you use a StateManager for your application, for example GetX
is a good solution. Create a controller file like the below:
// define this enum outside of class to handle the state of the page for load data
enum AppState { initial, loading, loaded, error, empty, disabled }
Rx<AppState> pageState = AppState.initial.obs;
class AttendanceCntroller extends GetxController{
RxList<dynamic> dataList=RxList<dynamic>();
#override
void onInit() {
//you can write other codes in here to handle data
pageState(AppState.loading);
dataList.value=
SupervisorAttendanceServices.getAttendancesDetailsList(attendanceId);
pageState(AppState.loaded);
super.onInit();
}
}
and in your view(UI) page, handle it in this way:
class AttendanceView extends GetView<AttendanceCntroller>{
#override
Widget body(BuildContext context) {
// TODO: implement body
return Obx( ()=> controller.pageState.value==AppState.loading ? const
Center(child: LinearProgressIndicator()) : ListView.builder(
itemCount: controller.dataList.length,
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemBuilder: (BuildContext context, int index) {
return HamalAttendanceWidget(
workerId: controller.dataList['worker_id'],
name: controller.dataList['worker_name'],
wages: newWages,
masterAttendanceId: widget.attendanceId,
isPrensent: controller.dataList[index]
['attendance_worker_presense']
.toString());
})
)
}
}
for more data read the GetX link and read clean architecture with the GetX sample repository of my GitHub it have advanced management of states with GetX with dependency injection handling.
If you want to have prefilled value in TextFormField, you can either use initialValue or controller parameter.
The value of controller parameter will help you to get/update the value of TextFormField.
For controller parameter refer below.
TextEditingController controller = TextEditingController(text: 'This is text will be pre-filled in TextFormField');
...
TextFormField(
controller: controller,
);
Create List or Map of those controllers.
List<TextEditingController> listOfControllers = [ controller1, controlle2,...];
Use for loop through this List on onClick() method of Button.
ElevatedButton(
onPressed: () {
for(var controllerItem in listOfControllers) {
print(controllerItem.text); // the value of TextFormField
}
},
)
Please help me!!!
I m new in flutter, i want to create like this in my flutter app on button click.
Try below code,
showModalBottomSheet(
context: context,
builder: (BuildContext cntx) {
return Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
ListTile(
leading: Icon(Icons.camera),
title: Text("Camera"),
onTap: () async {
},
),
ListTile(
leading: Icon(Icons.image),
title: Text("Files")),
onTap: () async {
},
),
Container(
height: 50,
color: prefix0.appBackgroundColcor,
child: ListTile(
title: Center(
child: Text(
"Cancel",
style: TextStyle(color: Colors.white),
),
),
onTap: () {
Navigator.pop(context);
},
),
)
],
);
});
You can use cupertino bottom modal to achieve something like that. See below code for implementation:
void show() {
showCupertinoModalPopup(
context: context,
builder: (BuildContext cont) {
return CupertinoActionSheet(
actions: [
CupertinoActionSheetAction(
onPressed: () {
print('Camera');
},
child: Text('Use Camera'),
),
CupertinoActionSheetAction(
onPressed: () {
print('Upload files');
},
child: Text('Upload from files'),
),
CupertinoActionSheetAction(
onPressed: () {
print('Dropbox');
},
child: Text('Upload from DropBox'),
)
],
cancelButton: CupertinoActionSheetAction(
onPressed: () {
Navigator.of(cont).pop;
},
child: Text('Cancel', style: TextStyle(color: Colors.red)),
),
);
});
}
Call the show function with the press of any button. You will see something like this.
If you don't want the divider between actions you have to create your own custom popup.
I'm implementing this products app where a user can add a product from his wish list and add it to their cart. Once the user clicks the add to cart button, I want to delete the product from the screen and display a "success" Snackbar.
Since the products are loaded and displayed from FireBase Firestore, I delete the item and call setState({}); so that the list on the screen will be updated. The problem is that the SnackBar that comes right after setState({}); isn't shown.
I assume it is because the widget tree is rebuilt so the current state and context are "gone".
I tried finding some information online but haven't managed to find anything useful. I also tried to make a workaround with a bool flag that will be set once the user clicks the "Add to cart" button using and on setState the flag will be true one time to show the SnackBar when the widget tree is rebuilt and then turn the flag back to off but it didn't work as well.
What am I missing? How can I display a SnackBar after calling setState({})?
here is my code: (line in question marked with FIXME:)
slidable package installation
final GlobalKey _repaintBoundaryKey = GlobalKey();
final GlobalKey<ScaffoldState> _scaffoldKeyWishList = new GlobalKey<ScaffoldState>();
final Center _circularProgressIndicator = Center(
child: SizedBox(
width: 60,
height: 60,
child: CircularProgressIndicator(
valueColor: new AlwaysStoppedAnimation<Color>(Colors.lightGreen[800]),
)
),
);
#override
Widget build(BuildContext context) {
return Material(
child: FutureBuilder(
future: FirebaseFirestore.instance.collection("Wishlists").doc(FirebaseAuth.instance.currentUser.uid).get(),
builder: (BuildContext context, AsyncSnapshot<DocumentSnapshot> wishListSnapshot) {
if (wishListSnapshot.connectionState != ConnectionState.done) {
return _circularProgressIndicator;
} else if (!wishListSnapshot.hasData ||
0 == wishListSnapshot.data.data()['Wishlist'].length) {
return globals.emptyListErrorScreen(context, 'Wishlist');
}
int totalProducts = wishListSnapshot.data.data()['Wishlist'].length;
return Scaffold(
key: _scaffoldKeyWishList,
backgroundColor: Colors.lightGreen[800],
body: SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
ClipRRect(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(20.0),
topRight: Radius.circular(20.0),
),
child: Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
color: Colors.white,
child: ListView.builder(
itemCount: totalProducts * 2,
shrinkWrap: true,
padding: const EdgeInsets.all(16),
itemBuilder: (BuildContext _context, int i) {
if (i >= 2 * totalProducts) {
return null;
}
if (i.isOdd) {
return Divider(
color: Colors.green,
thickness: 1.0,
);
}
var wishlistIdData = wishListSnapshot.data.data()['Wishlist'];
String productID = wishlistIdData[i ~/ 2];
return FutureBuilder(
future: FirebaseFirestore.instance.collection("Products").doc(productID).get(),
builder: (BuildContext context, AsyncSnapshot<DocumentSnapshot> productSnapshot) {
if (wishListSnapshot.connectionState != ConnectionState.done || !productSnapshot.hasData) {
return _circularProgressIndicator;
}
var productData = productSnapshot.data.data()['Product'];
String prodName = productData['name'];
String prodPrice = productData['price'];
String prodDate = productData['date'];
return Slidable(
actionPane: SlidableDrawerActionPane(),
actionExtentRatio: 0.22,
direction: Axis.horizontal,
actions: <Widget>[
//add to cart
IconSlideAction(
caption: 'Add to cart',
color: Colors.transparent,
foregroundColor: Colors
.amberAccent,
icon: Icons.add_shopping_cart,
onTap: () async {
globals.userCart.add(
globals.Product(
productID,
FirebaseAuth.instance.currentUser.uid,
prodName,
double.parse(prodPrice),
prodDate,
[],
"",
"")
);
///removing product from wishlist
List toRemove = [];
toRemove.add(productID);
await FirebaseFirestore.instance
.collection('Wishlists')
.doc(FirebaseAuth.instance.currentUser.uid)
.get()
.then((value) async {
List<dynamic> list = List
.from(value
.data()['Wishlist']);
list
..removeWhere((e) =>
toRemove.contains(e));
await FirebaseFirestore.instance
.collection('Wishlists')
.doc(FirebaseAuth.instance.currentUser.uid)
.update(
{'Wishlist': list});
});
setState(() {
///to update the list on screen
});
//FIXME: snackbar not displayed after setState!
///showing snackbar upon completion
_scaffoldKeyWishList
.currentState
.showSnackBar(
SnackBar(
content: Text(
'Product Successfully Added to Cart!',
style: GoogleFonts
.lato(
fontSize: 13.0,
color: Colors
.white
),
),
behavior: SnackBarBehavior
.floating,
action: SnackBarAction(
label: 'Checkout',
textColor: Colors
.lime,
onPressed: () =>
showDialog(
context: context,
builder: (
BuildContext context) {
return CustomDialogBox();
},
),
),
)
);
},
),
],
child: ListTile(
title: Text(prodName,
style: GoogleFonts.lato(
fontSize: 18.0,
color: Colors.black,
),
),
subtitle: Text(prodPrice + "\$",
style: GoogleFonts.lato(
fontSize: 13.5,
color: Colors.grey,
),
),
visualDensity: VisualDensity
.adaptivePlatformDensity,
),
);
},
);
},
),
)
)
]
)
)
);
}
)
);
}
In my case I was calling setState method before build method complete process of building widgets.
You can face this error if you are showing snack bar or alert dialog before the completion of build method and in many other cases. so in such situation use below call back function.
WidgetsBinding.instance.addPostFrameCallback((_) {
// add your snackbar code here
});
or You can also use SchedulerBinding which does the same.
SchedulerBinding.instance.addPostFrameCallback((_) {
// add your code here of snackbar.
});
or you can try this too (I am not sure about this one)
if(mounted){
//add your code here of snackbar
}
CREDITS
Currently I am trying to develop a BottomSheet that expands to a specific size. When that size is reached, the user should be able to drag the BottomSheet a little bit up. I have implmented the GestureDetector inside the BottomSheet, so that I am able to detect a vertical drag. The drag function is called, but unfortunately it is not changing the size of the BottomSheet.
This is my code:
//These values are outside of the classes
double initial;
double _kShoppingMenuHeight;
//My custom BottomSheet with rounded corner
Future<T> showRoundedBottomSheet<T> ({
#required BuildContext context,
#required Widget child,
double height
}) {
assert(context != null);
assert(child != null);
return showModalBottomSheet(
context: context,
builder: (BuildContext context){
return new Container(
height: (height != null
? height
: 400.0
),
color: Color(0xFF737373),
child: new Container(
decoration: new BoxDecoration(
color: Colors.white,
borderRadius: new BorderRadius.only(
topLeft: const Radius.circular(5.0),
topRight: const Radius.circular(5.0)
)
),
child: Builder(
builder: (BuildContext context){
return child;
},
)
),
);
}
);
}
//The function that opens the BottomSheet
// this is in another class
return showRoundedBottomSheet(
context: context,
height: _kShoppingMenuHeight,
//Make bottomsheet draggable and fixed at specific point
child: ShoppingMenu(
title: _title("Ihre Listen"),
items: items
)
);
//The stateful widget with the content
return GestureDetector(
onVerticalDragStart: (DragStartDetails details){
initial = details.globalPosition.dy;
},
onVerticalDragUpdate: (DragUpdateDetails details){
setState(() {
_kShoppingMenuHeight = MediaQuery.of(context).size.height / 2 - details.globalPosition.dy;
if(_kShoppingMenuHeight.isNegative) _kShoppingMenuHeight = _kShoppingMenuHeight * (-1);
});
},
onVerticalDragEnd: (DragEndDetails details){
},
child: NotificationListener<OverscrollIndicatorNotification>(
onNotification: (overscroll){
overscroll.disallowGlow();
},
child: ConstrainedBox(
constraints: BoxConstraints(
minHeight: _kShoppingMenuHeight
),
child: ListView(
physics: NeverScrollableScrollPhysics(),
children: <Widget>[
Padding(
padding: EdgeInsets.only(top: 30.0, left: 10.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Padding(
padding: EdgeInsets.only(bottom: 10.0),
child: widget.title,
),
Column(
children: widget.items
)
],
),
),
Divider(),
GestureDetector(
child: ListTile(
leading: Icon(Icons.add, color: Colors.black54),
title: Text(
"Neue Liste erstellen"
),
),
onTap: (){
Navigator.pop(context, "neue Liste");
},
),
Divider(),
GestureDetector(
child: ListTile(
leading: Icon(OMIcons.smsFailed, color: Colors.black54),
title: Text(
"Feedback geben"
),
),
onTap: (){
Navigator.pop(context, "feedback");
},
)
],
),
),
),
);
This is a complete example of how you can drag around with your modal bottom sheet.
The idea is to wrap the content of the sheet by a stream builder ,and update the stream when drag occurs. let me know if you need further explanation.
import 'package:flutter/material.dart';
import 'dart:async';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('My App'),
),
body: MyWidget(),
),
);
}
}
StreamController<double> controller = StreamController.broadcast();
class MyWidget extends StatefulWidget{
#override
_MyWidgetState createState() => _MyWidgetState();
}
class _MyWidgetState extends State<MyWidget> {
double position;
#override
Widget build(BuildContext context) {
return Container(
child: Center(
child: RaisedButton(
child: Text('Show Buttom Sheet'),
onPressed: () {
showModalBottomSheet(context: context, builder: (context){
return StreamBuilder(
stream: controller.stream,
builder:(context,snapshot) => GestureDetector(
onVerticalDragUpdate: (DragUpdateDetails details){
position = MediaQuery.of(context).size.height- details.globalPosition.dy;
print('position dy = ${position}');
position.isNegative?Navigator.pop(context)
:controller.add(position);
},
behavior: HitTestBehavior.translucent,
child:
Container(
color: Colors.red,
height: snapshot.hasData ? snapshot.data:200.0,
width: double.infinity,
child: Text('Child'),
)),
);
});
}),
),
);
}
}
I think setState() call on the wrong widget.
setState() need to be called on the widget holding the Scaffold because bottom sheet belongs to the scaffold itself .
inherited widget may be the solution
I have the following AlertDialog.
showDialog(
context: context,
child: new AlertDialog(
title: const Text("Location disabled"),
content: const Text(
"""
Location is disabled on this device. Please enable it and try again.
"""),
actions: [
new FlatButton(
child: const Text("Ok"),
onPressed: _dismissDialog,
),
],
),
);
How can I make _dismissDialog() dismiss said AlertDialog?
Navigator.pop() should do the trick. You can also use that to return the result of the dialog (if it presented the user with choices)
Navigator.of(context, rootNavigator: true).pop('dialog')
worked with me.
Navigator.pop(_)
worked for me, but the Flutter Team's gallery contains an example using:
Navigator.of(context, rootNavigator: true).pop()
which also works, and I am tempted to follow their lead.
If you don't want to return any result, use either of them:
Navigator.of(context).pop();
Navigator.pop(context);
But if you do want to return some result, see this
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
}
});
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 the result call, try
Navigator.pop(context,result);
OR
Navigator.of(context, rootNavigator: true).pop(result);
Navigator.of(dialogContext).pop() otherwise you can close page if you navigated from Master to Detail page
showDialog(
context: context,
builder: (dialogContext) {
return Dialog(
child: Column(
children: [
Text("Content"),
RaisedButton(
onPressed: () => Navigator.of(dialogContext).pop(),
child: Text("Close"),
)
],
),
);
},
);
Example of dismissing alert dialog on flat button click
RaisedButton(
onPressed: () {
showDialog(
context: context,
builder: (context) => AlertDialog(
title: Text('Are you sure?'),
content: Text('Do you want to remove item?'),
actions: <Widget>[
FlatButton(
onPressed: () => Navigator.of(context).pop(false),// We can return any object from here
child: Text('NO')),
FlatButton(
onPressed: () => Navigator.of(context).pop(true), // We can return any object from here
child: Text('YES'))
],
)).then((value) =>
print('Selected Alert Option: ' + value.toString()));
},
child: Text('Show Alert Dialog'),
),
Above code have two unique things which is used to provide callback result of dialog
Navigator.of(context).pop(false) -- return false value when we pressed
NO Navigator.of(context).pop(true) -- return true value when we
pressed YES
Based on these return value, we can perform some operation outside of it or maintain the dialog status value
This works Prefectly
RaisedButton(
child: Text(
"Cancel",
style: TextStyle(color: Colors.white),
),
color: Colors.blue,
onPressed: () => Navigator.pop(context),
),
This worked for me Navigator.of(context, rootNavigator: true).pop('dialog').
Navigator.pop() just closes the current page/screen.
Creating a separate context for Alert Dialog would help.
showDialog(
context: context,
builder: (alertContext) => AlertDialog(
title: const Text("Location disabled"),
content: const Text(
"""Location is disabled on this device. Please enable it and try again."""),
actions: [
new FlatButton(
child: const Text("Ok"),
onPressed: () => Navigator.pop(alertContext),
),
],
),
);
Please use following for code to close dialog
RaisedButton(
onPressed: () { Navigator.of(context).pop();},
child: Text("Close",style: TextStyle(color: Colors.white), ),
color: Colors.black,
)
Use Navigator.pop(context);
Example
showDialog(
context: context,
child: new AlertDialog(
title: const Text("Location disabled"),
content: const Text(
"""
Location is disabled on this device. Please enable it and try again.
"""),
actions: [
new FlatButton(
child: const Text("Ok"),
onPressed: () {
Navigator.pop(context);
},
),
],
),
);
This answer works if you want to pop the dialog and navigate to another view. This part 'current_user_location' is the string the router need to know which view to navigate to.
FlatButton(
child: Text('NO'),
onPressed: () {
Navigator.popAndPushNamed(context, 'current_user_location');
},
),
This enough to dismisss dialog add inside Any callback like onpressed,ontap
Navigator.of(context).pop();
AlertDialog(
title: Center(child: Text("$title")),
insetPadding: EdgeInsets.zero,
titlePadding: EdgeInsets.only(top: 14.0, bottom: 4),
content: Container(
height: 50,
child: TextFormField(
controller: find_controller,
decoration: InputDecoration(
suffixIcon: context.watch<MediaProvider>().isChangeDialog
? IconButton(
onPressed: () {
clearController(find_controller);
},
icon: Icon(Icons.clear))
: null,
border: OutlineInputBorder(
borderSide: BorderSide(color: Colors.deepPurpleAccent)),
hintText: 'Id',
),
onChanged: (val) {
if (val.isNotEmpty)
context.read<MediaProvider>().isChangeDialog = true;
else
context.read<MediaProvider>().isChangeDialog = false;
},
),
),
actions: [
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Padding(
padding: const EdgeInsets.all(4.0),
child: OutlinedButton(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Align(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 12.0),
child: Icon(Icons.clear),
),
),
Text("Cancel")
],
),
onPressed: () {
context.read<MediaProvider>().isChangeDialog = false;
//========================this enough to dismisss dialog
Navigator.of(context).pop();
}),
),
Padding(
padding: const EdgeInsets.all(4.0),
child: ElevatedButton(
onPressed: context.watch<MediaProvider>().isChangeDialog
? () {
context.read<MediaProvider>().isChangeDialog = false;
okCallback;
}
: null,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Align(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 12.0),
child: Icon(Icons.check),
),
),
Text("OK")
],
)),
)
],
),
],
);
pass it in the showDialog
barrierDismissible : true
use get package.
then Get.back() to close Modal
For Closing Dialog
void cancelClick() {
Navigator.pop(context);
}
The accepted answer states how to dismiss a dialog using the Navigator Class. To dismiss a dialog without using Navigator you can set the onPressed event of the button to the following:
setState((){
thisAlertDialog = null;
});
In case the code above is not self-explanatory it is basically setting the Parent AlertDialog of the FlatButton to null, thus dismissing it.