PersistentBottomNavBar
PersistentBottomNavBar copied to clipboard
ModalRoute.of(context).settings.arguements always null
in my route, i route from StoreItemsScreen -> StoreItemScreen. both screens are under the "home" tab of the persistent navigation bar. I am using named routes. StoreItemScreen needs to accept an arguement to work, yet ModalRoute.of(context).settings.arguements is always null no matter what i do. i have simplified the code a bit, but still kept all the important bits. Why is ModalRoute.of(context).settings.arguements always null? and how can i pass data to this named screen?
Routes.dart
final Map<String, Widget Function(BuildContext)> AppRoutes = {
"/storeItems": (_) => StoreItemsScreen(),
"/storeItem": (context) => StoreItemScreen(),
};
navigation to store item screen
Navigator.of(context).pushNamed('/storeItem', arguments: {"item": "test"});
StoreItemScreen
class StoreItemScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
final args = ModalRoute.of(context)!.settings.arguements;
print(args); // **--> always null**
return Scaffold(
body: Container(),
);
}
NavBarItems
List<PersistentBottomNavBarItem> getNavBarItems(BuildContext context) {
return [
PersistentBottomNavBarItem(
icon: Icon(Icons.person),
title: (AppLocalizations.of(context)!.profile),
routeAndNavigatorSettings:
RouteAndNavigatorSettings(initialRoute: '/profile', defaultTitle: 'profile', routes: AppRoutes),
),
PersistentBottomNavBarItem(
icon: Icon(Icons.home),
title: (AppLocalizations.of(context)!.home),
routeAndNavigatorSettings:
RouteAndNavigatorSettings(initialRoute: '/home', defaultTitle: 'home', routes: AppRoutes),
),
PersistentBottomNavBarItem(
icon: Icon(Icons.receipt_outlined),
title: (AppLocalizations.of(context)!.my_orders),
routeAndNavigatorSettings:
RouteAndNavigatorSettings(initialRoute: '/orders', defaultTitle: 'orders', routes: AppRoutes),
),
];
I'm struggling to figure out how this is meant to work also, I've set up a replicable example in a repo here.
Here's how I've been attempting to set it up:
main.dart
import 'package:flutter/material.dart';
import 'package:persistent_bottom_nav_bar/persistent-tab-view.dart';
import 'package:flutter_nav_bar_routing/screens/screen_a.dart';
import 'package:flutter_nav_bar_routing/screens/screen_b.dart';
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Persistent Bottom Nav Bar example project',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: AppView(),
);
}
}
class AppView extends StatefulWidget {
@override
_AppViewState createState() => _AppViewState();
}
class _AppViewState extends State<AppView> {
final PersistentTabController _controller =
PersistentTabController(initialIndex: 0);
String? module;
@override
Widget build(BuildContext context) {
return PersistentTabView(
context,
controller: _controller,
decoration: NavBarDecoration(boxShadow: [BoxShadow()]),
screens: _buildScreens(),
items: _navBarsItems(),
navBarStyle: NavBarStyle.style14,
);
}
List<Widget> _buildScreens() {
return [
ScreenA(),
Container(),
];
}
List<PersistentBottomNavBarItem> _navBarsItems() {
return [
PersistentBottomNavBarItem(
title: 'Home',
icon: Icon(Icons.home),
routeAndNavigatorSettings: RouteAndNavigatorSettings(
initialRoute: '/page/one',
routes: {
'/page/one': (context) => ScreenA(),
'/page/two': (context) => ScreenB(),
},
)
),
PersistentBottomNavBarItem(
title: 'Help',
icon: Icon(Icons.help)
),
];
}
}
void main() async {
runApp(new MyApp());
}
screen_a.dart
import 'package:flutter/material.dart';
import 'package:flutter_nav_bar_routing/page_arguments.dart';
class ScreenA extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Navigation with params'),
),
body: Center(
child: ElevatedButton(
child: Text('Click me!'),
onPressed: () {
Navigator.pushNamed(
context,
'/page/two',
arguments: PageArguments(
id: 1,
title: "Example Title"
),
);
},
),
),
);
}
}
screen_b.dart
import 'package:flutter/material.dart';
class ScreenB extends StatelessWidget {
@override
Widget build(BuildContext context) {
final arguments = ModalRoute.of(context)!.settings.arguments;
print("Route name is:");
print(ModalRoute.of(context)!.settings.name);
// The result of this is `/page/one` ?
print("Route arguments are:");
print(arguments);
// The result of this is `null`.
return Scaffold(
appBar: AppBar(
title: Text('Parameter example'),
),
body: Center(
child: Text("Parameter example"),
),
);
}
}
page_arguments.dart
class PageArguments{
final int id;
final String title;
PageArguments({required this.id, required this.title});
}
Any input would be great, as at this stage I suspect I'm going about it the wrong way, but I haven't been able to find any examples of this implemented.
@Seanmcn this seems like the idea I'm trying to get across, yes. the arguments are always Null, and the Name is wrong. this means i am not currently able to use a named route AND pass arguments around, i have to either use named routes without passing arguments, or not use named routes.
The original idea really was that i wanted to use a very clean-looking way to pass things around with named routes i found in an answer somewhere, where i write in "routes":
routes: {
'/page/one': (context) => ScreenA(),
'/page/two': (context) => ScreenB(ModalRoute.of(context).settings.arugments), // here
},
which would have made things more easier and consistent to use with named routes, but as modalRoute has this issue, this is impossible to do.
@evanholt1 i have the same problem to pass arguments to another screen, do you how can we resolve this problem? could you fix that?
@pishguy Sorry, i was not able to find a way to solve this. The way i ended up going for was using "pushNewScreenWithRouteSettings", using they key from the AppRoutes map i defined. example:
AppRoutes.dart
final Map<String, Widget Function(BuildContext)> AppRoutes = {
"/storeItem" => (context) => StoreItemScreen(),
}
In a button which leads to StoreItemScreen
InkWell(
onTap: () => pushNewScreenWithRouteSettings(context,
screen: AppRoutes["/storeItem"]!(context),
settings: RouteSettings(name: '/storeItem', arguments: age )),
........
......
)
and in StoreItemScreen
@override
Widget build(BuildContext context) {
final int age= ModalRoute.of(context)!.settings.arguments as int;
.....
....
This was not ideal, but the only way i could get things done on time.
@evanholt1 thanks so much
i can resolve this problem by this solution:
PersistentBottomNavBarItem(
title: 'Home',
icon: const Icon(Icons.home),
routeAndNavigatorSettings: RouteAndNavigatorSettings(
initialRoute: '/page/one',
onGenerateRoute: (RouteSettings settings) {
switch (settings.name) {
case '/page/one':
return PageTransition(
child: ScreenA(),
type: PageTransitionType.fade,
duration: const Duration(milliseconds: 50),
reverseDuration: const Duration(milliseconds: 50),
settings: settings,
);
case '/page/two':
return PageTransition(
child: ScreenB(),
type: PageTransitionType.fade,
duration: const Duration(milliseconds: 50),
reverseDuration: const Duration(milliseconds: 50),
settings: settings,
);
default:
throw Exception('Invalid route: ${settings.name}');
}
})),