close Simple Dialog in flutter when setState needs to called - flutter

I'm having a problem calling Navigator.of(context).pop() on my onPressed property in SimpleDialogOption widget. I need to set the state and dismiss the dialog. But calling setState is preventing my dialog to close. Without setState the dialog closes. Here is my dialog
WidgetsBinding.instance.addPostFrameCallback((_) {
showDialog(
builder: (BuildContext context) {
return SimpleDialog(
children: _children(suburbs),
backgroundColor: Colors.white,
title: Text('Pick your suburb'),
);
},
context: context);
});
and the method I use for the list of the Dialog:
List<Widget> _children(List<Suburb> suburbs) {
return suburbs
.map((suburb) => SimpleDialogOption(
onPressed: () {
print('#####################');
setState(() {
postcode = suburb.name;
});
Navigator.of(context).pop();
},
child: Text(suburb.name)))
.toList();
}

you can await until the return value comes from the navigator.pop,
and then call a setState
WidgetsBinding.instance.addPostFrameCallback((_) async {
postcode = await showDialog(
builder: (BuildContext context) {
return SimpleDialog(
children: _children(suburbs),
backgroundColor: Colors.white,
title: Text('Pick your suburb'),
);
},
context: context);
setState(() {
postcode;
});
});
List<Widget> _children(List<Suburb> suburbs) {
return suburbs
.map((suburb) => SimpleDialogOption(
onPressed: () {
print('#####################');
Navigator.of(context).pop(suburb.name);
},
child: Text(suburb.name)))
.toList();
}

Related

How to check Alert Dialog is open only one times instead of multiple new dialog box after onTap in flutter

I am working on my flutter application and I want to check whether the alert dialog is open or not on the screen . Can anyone tell me how to do that, now everytime i press ontap and it will appear a new dialog box. how can i only appear one dialog box instead of multiple of new dialog box ?
I have try bool, ontap cancel all not working.
Future? _dialog;
Future<void> _checkTimer() async {
if (_dialog == null) {
_dialog = await Future.delayed(Duration(seconds: 5));
showTimer(context);
await _dialog;
_dialog = null;
} else {
//do nothing
}
}
showTimer(BuildContext context) {
// set up the buttons
// ignore: deprecated_member_use
if (didUserTouchedScreen = true){
Container alert = Container(child: _imageslideshowProductDetailstimer());
// show the dialog
showDialog(
barrierDismissible: true,
context: context,
builder: (BuildContext context) {
return WillPopScope(
onWillPop: () async {
didUserTouchedScreen = false;
// _checkTimer();
return true;
},
child: alert);
},
).then((_) => didUserTouchedScreen = false);
}}
behavior: HitTestBehavior.translucent,
onTapDown: (tapdown) {
print("down");
_checkTimer();
},
onTapCancel: (){print('up');_checkTimer();}
You can achieve this with a boolean state, let's call it isButtonActive. The button is enabled/disabled depending on the value of this state. When the button is pressed, set the state to false, and when the dialog box is closed, set the state to true.
Below is an example code:
class _HomePageState extends State<HomePage> {
bool isButtonActive = true;
showTimer(BuildContext context) async {
setState(() {
isButtonActive = false;
});
await Future.delayed(Duration(seconds: 2));
showDialog(
context: context,
builder: (BuildContext context) {
return Column(
children: const [
Text('qwerty'),
],
);
},
).then((value) {
setState(() {
isButtonActive = true;
});
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('총톤수'),
),
body: Center(
child: ElevatedButton(
onPressed: isButtonActive ? () => showTimer(context) : null,
child: const Text('총톤수'),
),
),
);
}
}

Flutter - Custom back button doesn't work

I have an alertdialog which is supposed to return a bool depending on the user's choice, the message gets removed, but the back button isn't working!
Future<bool?> showwarning(BuildContext context) async {
showDialog<bool>(
context: context,
builder: (context) => AlertDialog(
title: new Text("Alert!!"),
content: new Text("Return To Main Page?!"),
actions: [
TextButton(
child: new Text("Yes"),
onPressed: () {
Navigator.pop(context, true);
},
),
TextButton(
child: new Text("Nope"),
onPressed: () {
Navigator.pop(context, false);
},
)
],
));
}
Widget build(BuildContext context) {
// TODO: implement build
return WillPopScope(
onWillPop: () async {
final user_decision = await showwarning(context);
return user_decision ?? false;
},
Future<bool?> showwarning(BuildContext context) async {
return showDialog<bool>(
context: context,
builder: (context) => AlertDialog(
title: new Text("Alert!!"),
content: new Text("Return To Main Page?!"),
actions: [
TextButton(
child: new Text("Yes"),
onPressed: () {
Navigator.pop(context, true);
},
),
TextButton(
child: new Text("Nope"),
onPressed: () {
Navigator.pop(context, false);
},
)
],
));
}
Widget build(BuildContext context) {
// TODO: implement build
return WillPopScope(
onWillPop: () async {
final user_decision = await showwarning(context);
return user_decision ?? false;
},
The problem is that I wasn't returning anything from showwarning function , hence, it was always false!

In flutter, how do I dynamically update an alert dialog's action list?

I am trying to dynamically update an alert dialog's action list when something takes place in the alert dialog. Essentially, by default the dialog has a "Cancel" action button. But once the user does something in the dialog, I want it to have a "Cancel" and an "Accept" button. I have tried using a StatefulBuilder, which is how I am getting the rest of the dialog to update state. However, it is not working with the action buttons.
I've tried conditionally rendering the button, as well as generating a list to use for the dialog actions, and using setState to add to the list when an action takes place. Neither works, although other state updates within the dialog's content work with the StatefulBuilder. The dialog opens with only the "Cancel" action, and will not update to include the "Accept" action as well.
await showDialog<void>(
context: context,
builder: (BuildContext context) {
int? selectedRadio = 0;
return AlertDialog(
content: StatefulBuilder(
builder: (BuildContext context, StateSetter setState) {
return Column(
mainAxisSize: MainAxisSize.min,
children: List<Widget>.generate(4, (int index) {
return Radio<int>(
value: index,
groupValue: selectedRadio,
onChanged: (int? value) {
setState(() => selectedRadio = value);
},
);
}),
actions: <Widget>[
TextButton(
child: Text('Cancel'),
onPressed: () {
Navigator.of(context).pop();
},
),
selectedRadio == 1 ? TextButton(
child: Text('Accept'),
onPressed: () {
Navigator.of(context).pop();
},
) : SizedBox.Shrink(),
],
);
},
),
);
},
);
Try putting the AlertDialog inside the StatefulBuilder
return StatefulBuilder(
builder: (context, setState) {
return AlertDialog(
Create a StatefulWidget to display your AlertDialog, and manage selectedRadio there. Also take advantage of Dart's collection if to handle the conditional button:
class MyDialog extends StatefulWidget {
const MyDialog({Key? key}) : super(key: key);
#override
State<MyDialog> createState() => _MyDialogState();
}
class _MyDialogState extends State<MyDialog> {
int selectedRadio = 0;
#override
Widget build(BuildContext context) {
return AlertDialog(
actions: <Widget>[
TextButton(
child: Text('Cancel'),
onPressed: () {
Navigator.of(context).pop();
},
),
if (selectedRadio == 1)
TextButton(
child: Text('Accept'),
onPressed: () {
Navigator.of(context).pop();
},
)
],
content: Column(
mainAxisSize: MainAxisSize.min,
children: List<Widget>.generate(4, (int index) {
return Radio<int>(
value: index,
groupValue: selectedRadio,
onChanged: (int? value) {
setState(() => selectedRadio = value!);
},
);
}),
));
}
}
After this, you can display your dialog for example like this:
TextButton(
child: Text('Pressme'),
onPressed: () async => await showDialog<void>(
context: context,
builder: (BuildContext context) {
return const MyDialog();
},
))

wait until showdialog is closed flutter

I am trying to get the location permissions and I want to display a message before requesting the permission. but when I run the APP it doesn't wait until I close the showdialog
Future<void> checkPermission() async {
var status = await Permission.location.status;
print(status.toString());
if (status.isUndetermined) {
await showAlertPopup(context, '',
'OK')
.then((val) {
var statuses = Permission.location.request();
print(statuses);
});
}
if (status.isDenied ||
status.isPermanentlyDenied ||
status.isRestricted ||
status.isUndetermined) {
await showAlertPopup(context, '',
'error')
.then((val) {
openAppSettings();
});
}
if (status.isGranted) {
_geoAlowed = true;
}
}
and this is my code to display the popup
showAlertPopup(BuildContext context, String title, String detail) async {
showDemoDialog({BuildContext context, Widget child}) async {
showDialog(
context: context,
barrierDismissible: false,
builder: (BuildContext context) {
return child;
});
}
return showDemoDialog(
context: context,
child: AlertDialog(
title: Text(title),
content: Text(detail),
backgroundColor: grayLight,
actions: [
FlatButton(
child: Text('OK'),
onPressed: () {
Navigator.pop(context, 'OK');
},
),
],
),
);
}
As per your question, you want to request permission when user clicks 'OK' button in dialog.
You can create a callback, that is when user clicks 'OK'
showAlertPopup(context, '','OK', (){
//Code you want to execute when user clicks 'OK'
});
And little changes in you showAlertPopup
showAlertPopup(BuildContext context, String title, String detail, Function onClick) async {
showDemoDialog({BuildContext context, Widget child}) async {
showDialog(
context: context,
barrierDismissible: false,
builder: (BuildContext context) {
return child;
});
}
return showDemoDialog(
context: context,
child: AlertDialog(
title: Text(title),
content: Text(detail),
backgroundColor: grayLight,
actions: [
FlatButton(
child: Text('OK'),
onPressed: () {
//Your callback
onClick();
Navigator.pop(context, 'OK');
},
),
],
),
);
}

Statefulwidget is not refreshing ListView

I'm saving the data that is fetched from an API to the sqflite in flutter project, everything is working good, except that after clicking a raised button the data should be insert into the table and a new page should be open but there is no data unless I refresh that page so the data appear
As you can see, here is the code of the raised button:
RaisedButton(
child: Text('Get Cities'),
onPressed: () async {
setState(() {
GetAllData.data.Getdata();
});
await Navigator.push(context, MaterialPageRoute<void>(
builder: (BuildContext context) => StoreList()));
setState(() {});
},
)
Inside the setState I'm calling a function Getdata to get the data from the sqflite, after it getting it the app should open a new page
And below is the code of the page which should show the data in a ListView:
class StoreList extends StatefulWidget { #override
_StoreListState createState() => _StoreListState();}
class _StoreListState extends State<StoreList> {
#override void initState() {
super.initState();
setState(() {
DatabaseProvider_API.db.getRoutes();
});}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Stores List'),
),
body: FutureBuilder<List<Stores>>(
future: DatabaseProvider_API.db.getStores(),
builder: (context, snapshot){
if(snapshot.data == null){
return Center(
child: CircularProgressIndicator(),
);
}
else {
return ListView.separated(
separatorBuilder: (BuildContext context, int index){
return Divider();
},
itemCount: snapshot.data.length,
itemBuilder: (BuildContext context, int index){
String name = snapshot.data[index].sTORENAME;
String name_ar = snapshot.data[index].cITY;
return ListTile(
title: Text(name),
subtitle:Text (name_ar),
onTap: ()async{
setState(() {
});
await
Navigator.push(context, MaterialPageRoute<void>(
builder: (BuildContext context) => Category() ));
},
);
},
);
}
},
),
floatingActionButton: new FloatingActionButton(
onPressed: () {
setState(() {});
},
child: new Icon(Icons.update),
),
);
}
}
Try to add the await keyword before evoke GetAllData.data.GetData()
RaisedButton(
child: Text('Get Cities'),
onPressed: () async {
// await for new data to be inserted
await GetAllData.data.Getdata();
await Navigator.push(context, MaterialPageRoute<void>(
builder: (BuildContext context) => StoreList()));
setState(() {
dataFuture = GetAllData.data.Getdata();
});
},
)