Warning
Discontinued! Use go_router's StatefulShellRoute
instead (see an example here).
A go_router package add-on to improve tabbed navigation. It features a special ShellRoute that provides both the selected navigation item index and transition direction - regardless of the current route's nesting level or the user's navigation path.
:sparkles: Features
- Seamless integration with existing GoRouter setups.
- Provides the selected navigation item index no matter how deeply nested the current route is or how the user got there.
- Provides the direction the user came from so you can build awesome transitions based on the previous and current navigation item index.
- Nested navigation bar setups work without an issue.
- No need for global navigation bar controllers.
- Comes with an extension on GoRouter's CustomTransitionPage to allow for better control over your transitions.
- Comes with neat transition presets.
:rocket: Getting started
Note: You'll need to install the go_router
package seperately. This package no longer exports go_router
to allow you to set a specific version of go_router in your app if required.
Install it:
flutter pub add go_router_tabs
Import it:
import 'package:go_router_tabs/go_router_tabs.dart';
Now check out the example to see this awesome package in action!
:joystick: Usage
:boom: Breaking Changes from 0.3.0!
These changes allow for custom GoRoutes or ShellRoutes:
childPageBuilder
has been renamed tosubPageBuilder
.TabShellRoute
no longer sets the page builders of its sub-routes.- Instead, the
subPageBuilder
anddirection
are passed intoroutes
which is now aList Function()
. - See the Usage/TabShellRoute section for more details...
TabShellRoute
Because TabShellRoute().toShellRoute
is a ShellRoute
you can add it anywhere within your existing GoRouter routes list:
GoRouter(
routes: [
TabShellRoute().toShellRoute,
],
)
Both the builder
and pageBuilder
give you the index of the currently displayed sub-route - it even works when the current route is nested deep within a sub-route:
TabShellRoute(
builder: (context, state, index, child) {
return MyNavigationBarPage(
selectedIndex: index,
child: child,
);
},
).toShellRoute
The subPageBuilder
is an optional page builder for the sub-routes and is used to avoid duplicate code. It gives you the direction - useful for slide transitions for example - based on the previous and current sub-route. The direction parameter is actually a TextDirection Function()
and needs to be evoked inside your transitions builder to fetch the latest direction from the TabShellRoute.
TabShellRoute(
subPageBuilder: (context, state, direction, child) {
return TabTransitionPage(
key: state.pageKey, // IMPORTANT! DON'T FORGET!
child: child,
direction: direction,
transitionsBuilder: TabTransitionPage.verticalSlideFadeTransition,
);
},
).toShellRoute
routes
is a builder that comes with sub page builder (which is defined by you in subPageBuilder
) and direction parameters. Now you can add GoRoutes, ShellRoutes, TabShellRoutes or your own custom routes:
TabShellRoute(
builder: (context, state, index, child) {
return MyNavigationBarPage(
selectedIndex: index,
child: child,
);
},
subPageBuilder: (context, state, direction, child) {
return TabTransitionPage(
key: state.pageKey,
child: child,
direction: direction,
transitionsBuilder: TabTransitionPage.verticalSlideFadeTransition,
);
},
routes: (subPageBuilder, direction) => [
GoRoute(
path: "/first",
pageBuilder: (context, state) => subPageBuilder!(
context,
state,
child: const FirstScreen(),
),
),
CustomGoRoute(
path: "/second",
pageBuilder: (context, state) => subPageBuilder!(
context,
state,
child: const SecondScreen(),
),
),
],
).toShellRoute,
TabTransitionPage
This package also comes with TabTransitionPage
, an extension on GoRouter's CustomTransitionPage
.
TabTransitionPage
allows you to specify the in and out curves of a transition:
TabTransitionPage(
transitionInCurve: Curves.bounceOut,
transitionOutCurve: Curves.bounceOut,
);
The transitionsBuilder
comes with an additional direction
parameter - useful for slide transitions. You'll need to pass in the direction
parameter from the subPageBuilder
.
TabTransitionPage(
direction: direction,
transitionsBuilder: (context, animation, secondaryAnimation, direction, child) {
final slideTween = Tween<Offset>(
begin: direction == TextDirection.ltr
? const Offset(-1, 0)
: const Offset(1, 0),
end: const Offset(0, 0),
);
final secondarySlideTween = Tween<Offset>(
begin: const Offset(0, 0),
end: direction == TextDirection.ltr
? const Offset(1, 0)
: const Offset(-1, 0),
);
return SlideTransition(
position: slideTween.animate(animation),
child: SlideTransition(
position: secondarySlideTween.animate(secondaryAnimation),
child: child,
),
);
},
);
DON'T FORGET TO PASS THE KEY! Otherwise the transition won't work properly.
TabTransitionPage(
key: state.pageKey,
);
TabTransitionPage
also comes with some handy transition presets:
TabTransitionPage.horizontalPushTransition;
TabTransitionPage.verticalPushTransition;
TabTransitionPage.horizontalSlideFadeTransition;
TabTransitionPage.verticalSlideFadeTransition;
:information_source: Additional Information
Please don't hesitate to report any issues or feature requests on GitHub.