FlutterNavigationGenerator
FlutterNavigationGenerator is a builder to generate a navigator for your pages with a simple annotation.
Features
Generates a navigator class with:
- All routes (@flutterRoute, @flutterDialog or @flutterBottomSheet)
- Type safe navigation methods
- Navigate by GlobalKey so you can create mutliple navigators for nested navigation and don't require a context
- Flutter Navigation (no third party dependencies)
- Web support with automatic encoding and decoding of route arguments
Getting Started
First add the dependencies:
dependencies:
flutter_navigation_generator_annotations: current_version
flutter_navigation_generator_animations: current_version # Optional, for route animations
dev_dependencies:
flutter_navigation_generator: current_version
Create a navigator file and annotate the class in it with @flutterNavigator
:
@flutterNavigator
class MainNavigator with BaseNavigator {}
Then annotate your pages with @flutterRoute
:
@flutterRoute
class FirstPage extends StatefulWidget {
const FirstPage({super.key});
...
Run build runner and you can start using the navigator:
// In your Dependency Injection:
final myNavigator = MainNavigator();
...
MaterialApp(
key: myNavigator.navigatorKey,
onGenerateRoute: myNavigator.onGenerateRoute,
initialRoute: RouteNames.myHomePage,
),
...
myNavigator.goToSecondPage();
Customization
FlutterNavigator
navigatorClassName
: The name of the navigator class. Default:BaseNavigator
pageType
: The type of the generated pages, must extendPageRoute
. Default:MaterialPageRoute
, useNativeRouteAnimation
fromflutter_navigation_generator_animations
to have a native feel across Android, iOS and WebremoveSuffixes
: A list of suffixes to remove from the route name. Default:['Page', 'Screen', 'View', 'Widget']
(Note: the suffixes are removed from the end of the name, soFirstPage
becomesFirst
)unknownRoute
: The screen to use when a route is not found, similar to/use this for a 404 page on webdefaultGuards
: Adds these guards to all routes where no guards are specified. Useful for adding e.g. login guards without having to add them to every route. Guards must extendNavigatorGuard
. Note: Navigation can be continued by callingnavigator.continueNavigation()
. See the continueNavigation() method in the Navigator for more information
FlutterRoute
-
routeName
: The name of the route. Optionally use:name
to declare a parameter in the route for web. Defaults to use query parameters. Name must match the variable name included in the constructor (for example:/events/:eventId/sponsors
). Default:[className]
(converted to kebab-case, as recommended by Google for urls) -
methodName
: The name of the method. Default:goTo[ClassName]
-
returnType
: The return type of the route. Default:void
-
navigationType
: The type of navigation. Default:NavigationType.push
, valid options are:pushAndReplaceAll
,pushReplacement
,popAndPush
,push
anddialog
to specify a dialog andbottomSheet
to specify a bottom sheet -
generateMethod
: If a method should be generated for the route. Default:true
(More info in separate method/page section below) -
generatePage
: If a page should be generated for the route. Default:true
(More info in separate method/page section below) -
isFullscreenDialog
: If the route should be launched fullscreen. Default:false
(true`` for
dialogand
bottomSheet` navigation types) -
pageType
: The type of the generated pages, must extendPageRoute
. Default:MaterialPageRoute
-
guards
: A list of guards to use for this route. Guards are used to prevent navigation, they can be used to check if the user is logged in. Guards must extendNavigatorGuard
. Note: Navigation can be continued by callingnavigator.continueNavigation()
. See the continueNavigation() method in the Navigator for more information -
@flutterRouteConstructor
: The constructor to use for the route. Defaults to unnamed constructor. This can be any constructor or static method -
@FlutterRouteConstructor(routeName)
: routeName specifies for which FlutterRoute this constructor is used
@FlutterRoute(
routeName: 'custom-name',
returnType: bool,
navigationType: NavigationType.popAndPush,
)
class FirstPage extends StatelessWidget {
final int someValue;
final int someOtherValue;
const FirstPage({required this.someValue, this.someOtherValue = 1, super.key});
@flutterRouteConstructor
static FirstPage doubleValue(int someValue, {Key? key, int someOtherValue = 2}) => FirstPage(someValue: someValue * 2, key: key, someOtherValue: someOtherValue);
Separate method/page
For some projects, you may have multiple projects/packages/navigators and it can happen that you want to generate a method in a different navigator than the page.
An example would be a goToHelpScreen in a shared package and an implementation in different apps. In this case, you can use the generateMethod
and generatePage
options to generate only the method or only the page.
Note that the routeName
must be the same for both the method and the page.
If you want to generate different arguments for the page than the base Widget has, you can use the @flutterRouteConstructor
annotation to specify a named constructor to use for the method arguments.
// In your shared package:
@FlutterRoute(
generatePageRoute: false,
routeName: '/help',
)
class BaseHelp extends StatelessWidget {
final String appTitle;
const BaseHelp({required this.appTitle, super.key});
@getXRouteConstructor
static BaseHelp.implementationConstructor()
...
// In your implementation:
@FlutterRoute(
generateMethod: false,
routeName: '/help',
)
class Help extends StatelessWidget {
const Help();
Widget build(BuildContext context) {
return BaseHelp(appTitle: 'My app');
}
Nested navigators
To use nested Navigators, simply create a new instance of the navigator. This will create a new GlobalKey for the navigator. Use this key in a Navigator widget and you can navigate to the pages in the nested navigator.
// In your Dependency Injection:
final myNestedNavigator = MainNavigator();
...
Navigator(
key: myNestedNavigator.navigatorKey,
onGenerateRoute: myNestedNavigator.onGenerateRoute,
initialRoute: RouteNames.myHomePage,
),
...
myNestedNavigator.goToPageWithinNestedNavigation();
Deep linking to any page
Out of the box the navigator generates and supports url-only navigation. Meaning you can navigate to any page by providing the url. This is useful for deep linking and sharing links to specific pages. Simply use the navigator.navigatorKey.currentState?.pushNamed(url)
method to navigate to any page in your app.
If you want to improve UX it is recommended to set the parameters inside the routeName. This way the url will be more user friendly and easier to share. For example: /events/:eventId/sponsors
instead of /events/sponsors?eventId=123
.
Be aware that some screens you might not want to have navigation for (e.g. debug screens). In this case I suggest you use a guard to prevent navigation to these pages in production or add checks in the deeplinking method before calling pushNamed
.