How can I control what is passed to Navigator.pop() when clicking outside of a showModalBottomSheet? - flutter

I launch a modal bottom sheet, then use the data that is returned as its future.
var modalFuture = showModalBottomSheet(
// ...
);
modalFuture.then((data) {
// Use data
});
I return data to it from the modal widget with:
Navigator.pop(context, data);
This is working well when completing the modal interaction with a widget I've set up.
I encounter my issue when clicking outside of the modal. Clicking outside of the modal causes the modal to dismiss automatically (with a Navigator.pop(context) call?). I am okay with this closing interaction, but I would like to send data back with it (with a Navigator.pop(context, data) call). Is there anyway to override the implicit pop when clicking outside of a showModalBottomSheet modal?

You can wrap your ModalWidget with WillPopScope. You can see the example below
WillPopScope(
onWillPop: () async {
Navigator.pop(context, data);
return true; // return true if needs to be popped
},
child: ModelWidget(
…
),
);
This will ensure that Navigator.pop is called when auto popped using the back button.

Related

How can I change or override android/ios back button's action in flutter

I need to make a change in my page (changing a bool in setState etc...) when the user presses the back button.
I looked it up and I know people use WillPopScope to override the default "back" action, but in all of the examples they were just popping the page, and I need to do a custom function instead of that, and have no Idea how to do so.
my function looks like this, and I need to run in when the user pressed the back button:
Future<void> backToCats() async{
setState(() {
isLoaded=false;
});
if(isFromSearch){
loadCategories();
}
setState(() {
showingBrands=false;
isLoaded=true;
});
}
You can perform custom logic in the onWillPop argument of a WillPopScope widget. Just make sure to return true or false at the end to indicate whether the page is allowed to pop. WillPopScope will activate for the back button, and other actions that automatically navigate back such as swiping from the side of the screen on iOS.
For example, if you need to set a bool to false in your stateful widget, it would look something like this
WillPopScope(
onWillPop: () async {
setState(() => myBool = false);
return true;
}
child: ...
);

How can I call a function as soon as I go back to the main screen? - Flutter

Hello,
From the main screen of my app, pressing a button switches to another screen.
IconButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) {
return screen2();
},
),
);
},
When I am in screen2 and I want to go back or I can press a button.
Navigator.pop(context); or press the android back button.
How can I call a function as soon as I go back to the main screen?
Thank you.
From what I understood you want to trigger a function when you go to the previous page!
So,
Make the main screen as a Stateful widget and then initialize an init state and inside the init state put the function you want to trigger
Such as like this below code
#override
void initState() {
// TODO: implement initState
super.initState();
FunctionYouWantToTrigger();
}

How to call a function when returning to view/controller with `Get.back()`?

I am switching from the home view to another using Get.toNamed(Routes.DETAIL). When I want to return from the details view to the home view, I am calling Get.back() (or the user is using the back button of the devices).
Back on the home view, I would like to fetch all data from my database again.
Is there any function that is triggered when I am leaving a few and returning to it, so I can put my logic there?
Thank you
I would suggest you to use Get.offNamed() instead of Get.toNamed() as the offNamed() function will clear the data stored in catch and thus will again call the API declared in onInit() or onReady() lifecycle when returning back to that screen.
In Getx they have a funtion like
Get.back(result:"result");
so in order to trigger some funtion when going back to any page route
try doing this as the document written
final gotoHome = await Get.toNamed(Route.name); // or use the simple one Get.to(()=> Home());
then if you trigger to go back in page you should indicate some result e.g.
from back button in phone using willpopscope or a back button in UI.
Get.back(result:"triggerIt"); // this result will pass to the home.
so in will use
// It depend on you on where you gonna put this
// onInit or onReady or anything that would trigger
someTrigger() async{
final gotoHome = await Get.toNamed(Route.name);
if(gotoHome == "triggerIt"){
anyFuntionYouwantoTrigger();
}
}
for more info about it try to read the documentation.
https://github.com/jonataslaw/getx/blob/master/documentation/en_US/route_management.md
Edited: // Maybe some answer will pop up for better
I do have one but it's not that quite a real practice just a sample
e.g // sample you are now in the current page and this page is also connected to homecontroller or using Get.find() it need to bind the controller to the page;
class BindingHome with Bindings{
#override
void dependencies() {
Get.lazyPut(() => HomeController(), fenix: true);
}
}
then from GetPage add Binding
GetPage(
name: "/currentpage",
binding: BindingHome(),
page:() => HomeView(),
),
so while homecontroller is bind to the current page you are now so
// lets assume this one is put to the CurrentController
final homeController = Get.find<HomeController>();
so while calling back button on ui or willpopscope
when back try to trigger the function from home
gotBackfunction(){
Get.back();
homeController.anyFuntionYouwantoTrigger();
}
No you can't really call a function when doing so.
You should be using callback function just before popping the view.
onBackClick() async {
Get.lazyPut<MainController>(
() => MainController(),
);
controller.allItems.refresh();
Get.back();
}
Here is an example how you can do it without any complications:
WillPopScope(
onWillPop: () async {
await onBackClick();
return Future(() => false);
},
child: Scaffold(
appBar: CustomAppBarWithBack(
title: "Appbar",
OnClickBack: onBackClick,
),
body: Widget(),
),
);

Flutter - set result to return when the user navigates back

When calling Navigator.pop() a result can be passed to the previous screen. Is there a way to set the result so that if the user navigates back on their own the result is still returned to the previous page?
I could pass an object to the second page and then modify it so that the first page can check it when the second page returns, but I'd rather use the result returned from the Navigator as it's more readable.
Overriding the back button's tap detector as I've seen suggested elsewhere is not an acceptable solution because the user may navigate back in some other way such as swiping or pressing the Android back button.
Yes, you can pass data between screens both ways.
While popping back, send the data you wish to send like this from the second screen
RaisedButton(
onPressed: () {
// The Nope button returns "data" as the result.
Navigator.pop(context, 'data');
},
child: Text('Nope!'),
);
And catch the result in the your first screen like this
final result = await Navigator.push(
context,
MaterialPageRoute(builder: (context) => SecondScreen()),
);
source
For the other concern where the user is able to go back to the previous screen by pressing the back button, you can wrap your second screen with WillPopScope widget and provide the onWillPop callback. This will override the popping of the second screen and execute the callback where you can define the value you wish to return from the second screen.
#override
Widget build(BuildContext context) {
return WillPopScope(
child: Scaffold(), // or your widget
onWillPop: () {
return Future.delayed(Duration(microseconds: 0), () {
return Navigator.pop(context, "return-data");
});
},
);
}
Yes, this is possible, when navigating to Screen B from Screen A, make the onTap() functionasynchronous and await the result from Screen B.
Check the code below: It works perfectly:
On Screen A, put this code:
onTap: () async {
// receive the data you are sending from screen B here
final result = await Navigator.push( context);
},
On Screen B, put this code:
onTap: (){
// pass the data you want to use in screen A as the second paramter
Navigator.pop(context,number);
},
I hope this helps

How to hide alertDialog after one second with Navigator.of(context).pop()

I am trying to auto-hide an alertDialog after one second
This is the code:
Widget popupWidget(BuildContext context, ...) {
Future.delayed(Duration(seconds: 1), () {
Navigator.of(context).pop();
});
return AlertDialog(...);}
What works:
I can click somewhere else on the screen to close the alertDialog
I can wait for one second and it closes automatically
The bug:
If, after (exactly?) one second, I click somewhere else on the screen (which closes the alertDialog), the Future.delayed(...) will not hide the alertDialog, but the whole screen
I unsuccessfully tried making showDialog async, also tried the line
Navigator.of(context, rootNavigator: true).pop();
I think I've found a workaround with:
bool popupIsActive = true;
Future.delayed(Duration(seconds: 1), () {
if (popupIsActive) Navigator.of(context).pop();
});
and
showDialog(...).then((_) {
popupIsActive = false;
});
You might want to ignore any taps outside the dialog in order to prevent it from dismissing and just wait for the future to complete. You can set barrierDismissible to false in showDialog().