How can i empty a list in parent after back button is pressed and the user goes back to the parent from new material page route - flutter

I tried passing the parent as this in the pram and then call parent.parentList.clear();
but after doing so the the Navigator is not popping and neither the list is changing.
nyIdeas?
I tried passing an instance of a function from parent to child but but still the same problem the navigator does not pop.
return WillPopScope(
onWillPop: () {
parent.parentList.clear();
Navigator.pop(context);
}, child : code.....

I think you could do this by passing a function down to the child and then calling it before popping. Have a look at my answer here: Flutter - How to change state from inside another widget
Hope it helps!

Related

Return data when a screen is closed

I have several sub-screens which give the user the option to save some data. When that screen is closed, I want the parent screen, which pushed the sub-screen, to know whether data was saved or not. The sub-screens maintain a didSave flag and are set to true when data is saved.
There are several ways for the sub-screens to be closed:
hardware/software back button.
The close button on the AppBar.
A button on the screen itself.
I can handle the 3rd case using Navigator.pop(context, didSave) and in the parent that didSave flag is captured using final didSave = await Navigator.push<bool>(context, myRoute).
However, for the first 2 cases, the result will obviously be null.
I have looked into WillPopScope but that only is used to determine whether the screen should be closed or not. It doesn't seem that I can set any data to be returned for the push call.
I have also looked into wrapping the parent screen in a Provider where it can listen to didSave states but that will trigger immediately when emitted which is not desirable for my use case. I only want to act when the sub-screen is closed not when data is saved.
I can potentially use WillPopScope and emit an event there if a save operation has occurred but I would like a simpler solution if available.
Is there a way for this that I am missing?
Thanks!
as you said the Provider will listen to didSave and this doesn't fit in your case you can use just a simple inheritedWidget:
wrapping the parent like this:
InheritedExampleWidget(
didSave: false,
child: Parent(),
),
you need to set a setter to didSave
then on the ascendant widgets on the widget tree, you can:
InheritedExampleWidget.of(context).didSave = true;
this will not trigger it immediately, which the Provider package solves.
then you can manage the state however you want
Did you try to create the variable with state management? And there is method with the push that do task after user come from the child screen. So, when they come you can checkout the use have saved data or not.
For EG:
saved = false; //State management variable
//We are pushing on another screen.
Navigator.of(context).push(
MaterialPageRoute(
builder: (BuildContext context) =>
new ScreenName(),
),
).then((val) {
//This part with work when user popped the screen on which we have pushed
if (!saved) {//Do Something when not saved}
});
Try above code and let me know if you get any error or you're facing any issue.
when you push a new route, using StatefulWidget, it will have a lifecycle starting from an createState, when the widget isn't there on the widget tree ( when we pop ), the dispose method will be called.
those cases of popping the route:
hardware/software back button.
The close button on the AppBar.
A button on the screen itself.
will trigger the dispose method to execute.
so you can put inside it your logic that you want.
exmaple :
class classTest {
bool didSave = false;
}
then when on the property where you want to push the screen set it to that classTest's didSave, as an example:
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const YourRouteWidget(didSave: classTest.didSave,
),
),
);
on that point it's false, then when the user will complete using the screen, going back with any king of popping the route (with Navigator.pop(context), or with back button...), the dispose method will be called, so you can :
void dispose() {
if(/* your conditions*/ ) {
classTest.didSave = true;
}
super.dispose();
}
it will be back with a true value to the parent page.

Flutter dont close bottomSheet on BottomNavigationBar tap

I have a problem with a BottomNavigationBar. My app has two screens and one of them has a bottom sheet that doesn't hide on disposing of the first screen when I'm tapping on the icon of the second screen. BottomNavigationBar works normally and screens switch, but how to hide the bottom sheet of the first screen when shown the second screen I have no ideas. Could you help me solve that?
Calling:
void _showForm(int id) async {
showBottomSheet(
context: context,
elevation: 5,
builder: (context) => BottomSheetSwitch(_refreshJournals, id));
}
Closing (inside bottom sheet):
Navigator.of(context).pop();
P.S. I couldn't solve that problem, so I change showBottomSheet to showModalBottomSheet like that was in: how to set showModalBottomSheet to full height?
You can try to provide a key to the stateful widget of BottomSheet. And access that key's context just use the Navigator's pop method on tap or change of the screen. It might help you.
You can use it like
Navigator.of(key.currentContext).pop();
Else call the function of your BottomSheet using the key. Like as below
Declare GlobalKey with state in your currentWidget.
GloabalKey<BottomSheetWidgetState> closeKey = GloabalKey();
Declare one function closeBottomSheet in your bottomsheet widget state.
void closeBottomSheet(){ Navigator.of(conext).pop(); }
Call the function using the key.
closeKey.currentState.closeBottomSheet();
And done.

How to set a widget as a button in Flutter

I set two widgets in a Stack(), the one in the back is a sidebar and the one in the front is my main page.
When I click on the menu button from the main page, the main page gets shifted to the right and then the user can see the sidebar.
Now the problem is when the sidebar gets displyed i'm obliged to click exactly on the menu button to go back to the main page.
What i want to do is just to click anywhere in the main page to hide the sidebar.
I mean that i want to set the whole main page as a button when the sidebar is displayed.
You can use InkWell
InkWell(
onTap: (){
/// do something
},
child: Text('data') /// your widget,
),
You can also use GestureDetector
Generally if you want to make anything tappable you can just wrap the widget with GestureDetector
I fixed it by wrapping the main page with InkWell() and I added this to the onTap property"
InkWell(
onTap: isSidebarCollapsed ? () {
setState(() {
isSidebarCollapsed = false;
});
} : null,
child: Container(...)
)
Note that isSidebarCollapsed is the variable that determines if the menu is displayed or not.
Explaination of the code:
If the sidebar is collapsed (is displayed) then the onTap property returns a function where I set the variable isSidebarCollapsed to false (to say that the sidebar is gonna be hidden).
Else it returns null

How can add data on WillPopScope

I want add data at all 'pop'
It two case,
Android back key and some button for 'navigator.(context).pop()'
So I used WillPopScope but I can't add data like this
onWillPop: () async {
return Navigator.of(context).pop(myData));
},
this is not working.
How can I add data?
If you call
Navigator.of(context).pop(myData)
in your code, the pop with arguments will be delivered if onWillPop return true.
When popping a page, onWillPop has the duty to day "ok you can pop" or "ok you cannot".

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

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.