How do you reuse Flutter views created with MaterialPageRoute builder? - flutter

How do you reuse Flutter views created with MaterialPageRoute builder? Currently new views are created in the widget tree whenever Navigator.pushReplacementNamed is called. e.g. The following code will create 4 views in the widget tree:
Navigator.pushNamed(context, 'page1');
Navigator.pushNamed(context, 'page2');
Navigator.pushNamed(context, 'page1');
Navigator.pushNamed(context, 'page2');
I would prefer only two views in the widget tree - a single instance of both page1 and page2.
Is this possible?

push() and pushNamed() method recreate page over the current page you should use pushReplacement() and pushReplacementNamed() methods. However in this way you cannot use automatic back feature you should use pop() method or you should again some of push methods because when you you use pushReplacement() and pushReplacementNamed() methods previous page destroy and you should re-create manually.

Related

Is there a way to inject a widget UNDER the Navigator with GoRouter?

In the MaterialApp constructor, I am injecting a widget in the builder method to handle push notifications. To process foreground notification, I would like to use this widget to show a notification bar (using another_flushbar) but I need a Navigator in the context for that, and MaterialApp's builder injects above the Navigator, so when I try to using it to push my notification bar, there is no Navigator accessible via the context.
Of course, I could wrap every screen of my app with my notification-handling widget, but it defeats the purpose. I want a widget that is always on screen when the app is running, and that can show my notification bar, wherever I am in my app.
Any idea how I can do that?
Here is how I solved it, while still using MaterialApp's builder to inject my NotificationHandler widget ABOVE the Navigator.
My NotificationHandler widget accepts a GlobalKey<NavigatorState> navigatorKey property
When I initialize my NotificationHandler widget inside of MaterialApp's builder, I pass it GoRouter.routerDelegate.navigatorKey
Inside of NotificationHandler, when I need a context with a Navigator above it, I use navigatorKey.currentContext insted of my local widget context.
This solution was inspired by this issue.

In Flutter is there a way to check if the visible page has been presented modally

This is a common problem with iOS and is easily solved as all UIViewControllers have the property to check how they have been presented; whether modally or by being pushed onto a stack.
In Flutter we don't have view controllers, so we push new routes and one of the options is to use a fullScreenDialog. Your app bar will then have a close button and automatically pop when tapped.
But, if you want to dynamically adjust your Scaffold widgets based on whether they are presented in this way or not, there doesn't seem to be a way to detect that you are in a fullScreenDialog state (or modal). I have some pages that are part of the root tab navigation and therefore show a tab bar to switch between sections. I would like to reuse some of these pages but present them modally. In this case I want to remove the tab bar.
Is there any way to detect if a Navigator or Scaffold has been presented modally? Or do I just have to pass in a isModal bool?
I was thinking of perhaps a different solution based on your need and usecase.
It's respectable the you'd rather not repeat code just to get rid of an appBar when it's not needed.
Here's my suggestion, that would work with and take advantage of the framework rather than fight it.
Create your MultiPurposeSuperUsefulWidget, without a scaffold or appBar.
This widget can be shown easily without problems even needed with tabBar navigation.
The obstacle is wanting to use this in modal mode, you have the option to create this modal widget/screen template, that takes a final Widget widget constructor.
Customize this modal template in the way you like, and let's call it ModalTemplateScreen.
Finally, when you want your MultiPurposeSuperUsefulWidget to be displayed in modal style, navigate to ModalTemplateScreen(widget: MultiPurposeSuperUsefulWidget) and pass your reusable widget as an argument.
To set properties of your app bar based on modality you need to access the current Route and then check if the route was presented as a fullscreenDialog
isModal = (ModalRoute.of(context) as PageRoute).fullscreenDialog;

Problem with Mapbox navigation in flutter

I'm trying to make a turn by turn navigation app with flutter but I have a problem. I am using the Mapbox navigation package and I want the navigation screen to remain in the screen where I called it, not to open another screen. How can this be achieved?
if you are trying to navigate based on markers, you can do that using the ontap method inside the marker function.
onTap: (){
Navigator.push(context, MaterialPageRoute(builder: (context)=>Page()),);
}
you can do the navigation replacing the Page to which ever widget you want.

When popping , Why do we need to pass a context to Navigator in flutter?

Since flutter uses a stack to manage the screens which can be accessed through the Navigator class , I have the below understanding of it :
When we do Navigator.push(context , ... ) : Here the context is used so that it knows on top of which other widget it should push the new screen.
What I don't understand is why it needs a context to pop a screen out of view ?
Can't it simply pop the top most screen of the stack and show the screen below that ?
What exactly is the role of context here and how does it differ when pushing and popping
The reason is the same for both push and pop - it's to find the Navigator.
Looking at .pop you see that it's a static, convenience function that does:
return Navigator.of(context).pop<T>(result);
The context is used in .of to locate the navigator in the widget tree above the widget where you are calling push or pop. As you'd expect, of (another static convenience function) locates the actual navigator using:
context.findAncestorStateOfType()
So, in summary, you pass context so that context.findAncestor... can be used to find the navigator on which to call the method.

Flutter TabBar: Update tab (stateful widget) everytime a tab gets visible

happy new year! :)
I have three tabs, each holding a stateful widget. The data presented in tab #2 could be changed by the user within tab #3. Thus, when moving back from tab #3 to tab #2, I need to call an update() method within tab #2. Is there a stateful widget method that gets fired everytime the widget gets visible? If not, what opporutinites do I have in order to achieve this?
Best, Nico
The reason it's not updating is due to the widget already been rendered and now cached until the user exits the app. You can try numerous methods to make this work. For example, VoidCallBack method, adding an async function or leaving a blank setState in the initState itself. At the end of the day, it depends on how your app works. If you have a custom tabbar I'd recommend using the VoidCallBack method or maybe adding an async function which will be called before you return a render. Regardless these methods should work.