FlutterDriver - how to close showDialog [duplicate] - flutter

This question already has answers here:
How to close Dialog using FlutterDriver
(2 answers)
Closed 2 years ago.
I am working with FlutterDriver, I have an IconButton defined and a key set as shown:
Center(
child: IconButton(
key: Key('moredots'),
icon: Icon(Icons.more_vert),
onPressed: () {
showDialog(
context: context,
builder: (_) => tableConfig,
);
},
),
)
The dialog is successfully shown with the following code:
await driver.tap(find.byValueKey('moredots'));
What I can't figure out is how to dismiss the dialog. I've tried:
Tapping the same value as shown above
Adding a key in Scaffold, finding the key and tapping
Adding keys in other UI elements in the hierarchy, finding and tapping
The error message I receive is:
FlutterDriver: tap message is taking a long time to complete...

I figured out that showDialog() presents a ModalBarrier to stop user input while the dialog is shown.
The trick to close the showDialog is to find by type passing in the ModalBarrier as shown here:
await driver.tap(find.byType(ModalBarrier));

Add
Navigator.of(context).pop(false);
after
await driver.tap(find.byValueKey('moredots'));

Related

Flutter - How to detect if popupmenu has been closed or user tapped out of the menu to close it?

I am showing a popupmenu by calling the showMenu() method inside my custom appbar widget.
I need to be able to detect if user closed the popupmenu in anyway.
I tried using GestureDetector but it only detects taps when the popupmenu is already closed which is not what I need.
body: GestureDetector(
onTap: () => print('Tapped'),
child: MyWidget(),
),
Any ideas on how to solve this problem?
you can look at the PopupMenuButton documentation you will find it has a property called onCancelled you can read about it here
showMenu method returns a value, you should wait for. It returns either null (if menu has been closed in ANYWAY) or any value(if user selected menu button)
final result = await showMenu(...)
// you can detect close event even if user just dismissed menu like this:
if(result==null){...do something}
else{...use result}

Flutter: showing one dialog at a time

I am fairly new to state management in Flutter, and I have an application where the user will be interacting with dialogs, and a dialog may have a button to open another dialog which can result in the following:
https://i.stack.imgur.com/VBSzr.png
As shown, multiple issues arise when more than one is opened at once -- most notably the previous dialog is still visible in the background. So when a user opens a new dialog, is there any method where I can hide the dialog behind it, and when the frontmost dialog closes, show the previous one which is hidden? Thanks in advance.
Use Navigator.pop(context); method to close the dialog on your button's onPressed before opening the second dialog.
And then while closing your second dialog you can reopen your previous dialog.
Example:
showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: Text("Hello World"),
content: Text("This is content"),
actions: [
TextButton(
onPressed: () {
Navigator.pop(context); //Close your current dialog
//TODO:open your second dialog
},
child: Text("Open"))
],
);
});
I would first try to re-think the logic for opening multiple dialogs at the same time.
Maybe there is a quick workaround for that, but if you keep adding more and more dialogs, then it would become a mess.
Since showDialog<T> function returns Future<T?>, you could potentially use await and wait until the first dialog is closed and then open the second one and so on:
bool canContinue = await showDialog<bool>(
context: context,
builder: (context) => YourWidget(),
);
Alternatively, you could pop by using Navigator but as said, this will be visible to the user that something weird is going on (pushing and popping dialogs programatically).

Flutter pop best practice

I have the following flow Screen 1 -> Screen 2 -> Dialog (in a separate widget).
Screen 2 displays a dialog (Close? Yes or No). If someone presses Yes, I would like to return to the Screen 1, if they press No, just close the dialog and return to Screen 2. What I currently do is when Yes is tapped, I do Navigator.pop(context) twice. Is this a good practice? Is there a way to pass the context of Screen 2 to my dialog widget so I can pop that one directly?
Personally, I think it would be better to pass the response from the dialog back to the page, and let the page handle the rest.
You can do this:
//I'm using a raised button just to call the alert as an example...
RaisedButton(
child: Text('Press me'),
//This part here is the important part
onPressed: () async {
//You can return anything when you use Navigator.pop
//In this case I'm returning a bool indicating if the page should close or not.
//You have to await this because it depends on user input.
bool shouldPopResult = await showDialog<bool>(
context: context,
builder: (context) => AlertDialog(
//The content of your dialog
actions: <Widget>[
// The value you pass here in Navigator.of(context).pop
// is the value that will be stored in shouldPopResult,
// so if "Yes" is pressed, true will return...
// and if "No", false is returned.
FlatButton(
child: Text('Yes'),
onPressed: () => Navigator.of(context).pop(true),
),
FlatButton(
child: Text('No'),
onPressed: () => Navigator.of(context).pop(false),
)
],
),
);
// This is for if the user dismisses the dialog without pressing a button
// In that case shouldPopResult would be null, so I'm setting it to false.
// You can prevent the user from dismissing the dialog
// setting barrierDismissible to false in the showDialog method.
if (shouldPopResult == null) shouldPopResult = false;
// And finally with the dialog already dismissed, you can decide
// to go back or not.
if (shouldPopResult) Navigator.of(context).pop();
});
As usual you can extract the dialog as a Widget, or extract the function that handles the dialog response altogether or anything else.
You can see the example of returning data from a page in the flutter documentation here.

How do we pass or propagate data backwards through the Navigation stack in Flutter?

1.FlatButton(
onPressed: () async {
var typedName=await Navigator.push(
context,
MaterialPageRoute(
builder: (context) {
return CityScreen();
},
),
);
print(typedName); //prints the value of cityName
}
2. FlatButton(
onPressed: () {
Navigator.pop(context, cityName);
},
The no.1 is coming from file loading_screen and no.2 is coming from city_screen. Can you anyone help me understand what is happening that when you pass a variable or anything in the pop? And when come that onPress method is still working because the the method Navigator.push has been already assigned to the variable but still that method Navigator.push is working when I pressed the button?Does that onPress doesn't care about the variable TypedName and just looks for the method Navigator.push?
If you use push method it will create the new screen over your current page and pop will remove last screen, you cannot pass name with both, you can check basics of navigation here, if you want to pass name to next page you should use something like pushnamed method and you can see the logic of passing name here. And for all methods you should check here.

How to Perform 2 Different Action in One Button?

Example
How to open the url together with the snackbar in One button?
onTap: () => launch("http://flutter.dev"),
// when button tapped then url will be open and displaying a snackbar at a time
Discard the arrow function and write it like this
onTap: (){
launch("http://flutter.dev");
Scaffold.of(context).showSnackBar(SnackBar(content: Text("Message here"),));
},
onTap: () {
firstFunction();
secondFunction();
},
Please comment if I misunderstood your question.