Is it possible to use a separate Navigator in a pop up window? Separate BuildContext?
I have a working app (APP1) and I would like to show it in a new one (APP2) (e.g. on a button press to open the existing app). APP1 has multiple pages.
I was able add the APP1 as an dependency to APP2 and load the main page in a popup dialog (Alert dialog).
The issue happens when I try to navigate through the APP1. If I click on the button in the APP1 it changes the page in the whole new app.
I would like to have separate navigation in the pop up dialog, so that the included app Navigator works only in the pop-up dialog.
What would be a preferred/possible way to achieve this?
Here is a small example:
Soure code
The example consists of 2 apps (APP1 and APP2). APP2 includes APP1 and shows it in a pop up dialog.
You can add a nested Navigator (if you're using Navigator 1.0 in Flutter) by adding the Navigator widget inside your dialog component, that way you manage the navigation of pages within that dialog itself, create nested routes and navigate only within that navigation stack.
You can do something like:
class NestedDialog extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Navigator(
key: <ADD_UNIQUE_KEY>, // add a unique key to refer to this navigator programmatically
initialRoute: '/',
onGenerateRoute: (RouteSettings settings) {
// here you return your own page widgets wrapped
// inside a PageRouteBuilder
}
)
);
}
}
Then you can even use Flutter's own showDialog and load your custom dialog widget like so:
showDialog(context: context,
barrierDismissible: true,
builder: (BuildContext cxt) {
return AlertDialog(
content: NestedDialog()
);
});
Something along those lines. Give that a shot. Here's a Github Gist you can run on DartPad.dev so you can see what I mean. You don't have to create two apps; just distribute your app into two main widgets, and the child pages go under each main widget's child pages; See gist https://gist.github.com/romanejaquez/d769e6e766fbacb2f5c166dd3bceab51. Run it on DartPad.dev.
Related
I am really confused about how Flutter manages multiple navigation stacks at once, and switches between them with the BottomNavigationBar. So far I have managed to swap the body of my root Scaffold with Widgets, and can also change state on the Scaffold to change the AppBar title and set the index of the BottomNavigationBarItem. I can also see how setting routes on the MaterialApp will allow me to push and pop other screens. The problem is that when you have a tab bar navigation pattern, you want to be able to manage separate stacks. If I am 3 levels deep into a section and switch tabs, I expect to be in the stack for that particular section, and be able to jump between them.
How is this managed with Flutter? Ideally, the app should have a Main App Scaffold to define the BottomNavigationBar, the Drawer, and the main logic for switching between the different root level screens. These Screens should then manage their own AppBar and related actions for that section.
I'd really like to understand this before I go any further with Flutter, because right now, the thought of having to manage everything with one Scaffold fills me with dread.
I'm guessing that when you use Navigator it uses the Context to keep the stacks within the context of the screen that initiated the push, but I still don't understand how it keeps the Scaffold separate.
Any insight greatly appreciated.
This wonderful article gives me the answer: https://medium.com/flutter/getting-to-the-bottom-of-navigation-in-flutter-b3e440b9386
You need to use an IndexedStack for your main section switcher, and then use a Widget that returns a Navigator for each of the main sections. This Navigator sets the routes for that section (if known), but could just be the root.
I don't know if there is already a navigation pattern, or naming convention used by the Flutter community for this, but I have used $(Section)Navigator. Here's an example of a StatelessWidget I created for my test:
class DashboardNavigator extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Navigator(
onGenerateRoute: (RouteSettings settings) {
return MaterialPageRoute(
settings: settings,
builder: (BuildContext context) {
switch (settings.name) {
case '/':
return DashboardRoot();
case '/login':
return ScreenLogin(destination: allDestinations[0]);
default:
return DashboardRoot();
}
},
);
},
);
}
}
This was mainly taken from Hans Muller's article which has been a great help.
I have a flutter app that has the following drawer:
Routes:
Home: "/"
Nearby: "/nearby"
Applied: "/applied"
The behaviour I want to achieve is when the user clicks the android back button from nearby and applied screens, the app should take them to the home screen. If they press the back button from the home screen again it takes them out of the app.
Just to clarify here if they go to nearby, then to applied then click the back button it should take them to home, not applied.
Here is my code for navigating when nearby and applied drawer items are selected:
Navigator.pushNamedAndRemoveUntil(
context,
routeName,
ModalRoute.withName("/")
);
I expected this to leave the following routes in the stack:
home
selected page
But what I am getting is from nearby or applied screen when I tap the back button on android it takes me out of the app, rather than drop me to the home screen.
What am I missing? How can I achieve the behaviour I'm looking for?
Note that I know there's a solution using WillPopScope widget but I am looking for a solution that uses the navigation stack. More importantly I'm interested to know why the above scenario is not working.
Navigator.of(context).popUntil((route) => route.isFirst);
Add this WllPopCallBack() in NearBy and Apply widgets.
Future<bool> _willPopCallback() async {
Navigator.pushNamedAndRemoveUntil(
context,
routeName,
ModalRoute.withName("/")
);
return false; // return true if the route to be popped
}
Add this WllPopScope widget over Scaffold() in NearBy and Apply widgets like this:
new WillPopScope(child: new Scaffold(), onWillPop: _willPopCallback)
I am having trouble launching new screen widget. I have main.dart where I am using bottomNavigationBar and body for ViewPager UI. Now I have 3 bottom tabs and when I go to 2nd tab's view and click on a button to launch another screen/view using:
onTap: () => Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => ViewMyContactList(),
),
)
the new screen replaces the 2nd tab's view, when I go to 3rd tab then come back to 2nd tab, the new screen is gone and 2nd tab's initial screen is back. Also when new screen replaces the 2nd screen's initial view and when I do system back press in Android, the app exits straightaway.
You are trying to do Multiple Navigators with BottomNavigationBar
You can reference this doc for detail https://medium.com/coding-with-flutter/flutter-case-study-multiple-navigators-with-bottomnavigationbar-90eb6caa6dbf
Each tab must keep it'own Page Route, you can use the demo code in doc or
You can use the following two package to help you
https://pub.dev/packages/multi_navigator_bottom_bar
Helps you to build multi-navigator bottom navigation bar more easily.
https://pub.dev/packages/nested_navigators Flutter widget for implementing multiple nested navigators with their own route stacks.
I am using the Cupertino tab to display a bottom navigation bar and it working good. Now, I want to route to a new page from one of the tab pages (E.g login)and not have the bottom navigation. I tried the code below and I still see the bottom navigation.
How can I route to a page and not show the bottom navigation
Navigator.push(
context,
CupertinoPageRoute<void>(
title: "login",
builder: (BuildContext context) => LoginScreen(),
),
);
The static methods on Navigator, like Navigator.push or Navigator.of use the nearest enclosing Navigator of the context argument. When using a CupertinoTabScaffold, every tab has a nested Navigator to provide in-tab navigation, as is the default iOS behavior. You can get the root Navigator using Navigator.of(context, rootNavigator: true) and push your route on that:
Navigator.of(context, rootNavigator: true).push(route)
More info about navigators in the docs
I am currently working on an app using the flutter framework I have the main.dart file loading the homefeed page with bottom navigation bar with two tabs one for home and one for settings... The home.dart file is loading the body.dart whereas the body.dart file is loading list.dart and the problem occurs when I go to the settings tab and go back to the home tab the home page gets rebuilt. how can I keep all pages persistent?
To give you a basic idea:
home.dart:
Scaffold(
....
body: Body();
...
);
body.dart:
Scaffold(
...
body: List();
...
);
You can store necessary tabs state in the Home widget. When building tabs, pass appropriate state through constructor. When user switch tab, the state will persist because it's stored inside root widget.
If you'll need to pass the state to number of nested levels, consider using some packages like scoped_model, flutter_bloc or flutter_redux