Navigation Hub
Introduction
Navigation Hubs are a central place where you can manage the navigation for all your widgets.
Out the box you can create bottom, top and journey navigation layouts in seconds.
Let's imagine you have an app and you want to add a bottom navigation bar and allow users to navigate between different tabs in your app.
You can use a Navigation Hub to build this.
Let's dive into how you can use a Navigation Hub in your app.
Basic Usage
You can create a Navigation Hub using the below command.
dart run nylo_framework:main make:navigation_hub base
// or with Metro
metro make:navigation_hub base
This will create a base_navigation_hub.dart file in your resources/pages/
directory.
import 'package:flutter/material.dart';
import 'package:nylo_framework/nylo_framework.dart';
class BaseNavigationHub extends NyStatefulWidget with BottomNavPageControls {
static RouteView path = ("/base", (_) => BaseNavigationHub());
BaseNavigationHub()
: super(
child: () => _BaseNavigationHubState(),
stateName: path.stateName());
/// State actions
static NavigationHubStateActions stateActions = NavigationHubStateActions(path.stateName());
}
class _BaseNavigationHubState extends NavigationHub<BaseNavigationHub> {
/// Layouts:
/// - [NavigationHubLayout.bottomNav] Bottom navigation
/// - [NavigationHubLayout.topNav] Top navigation
/// - [NavigationHubLayout.journey] Journey navigation
NavigationHubLayout? layout = NavigationHubLayout.bottomNav(
// backgroundColor: Colors.white,
);
/// Should the state be maintained
@override
bool get maintainState => true;
/// Navigation pages
_BaseNavigationHubState() : super(() async {
return {
0: NavigationTab(
title: "Home",
page: HomeTab(),
icon: Icon(Icons.home),
activeIcon: Icon(Icons.home),
),
1: NavigationTab(
title: "Settings",
page: SettingsTab(),
icon: Icon(Icons.settings),
activeIcon: Icon(Icons.settings),
),
};
});
}
You can see that the Navigation Hub has two tabs, Home and Settings.
You can create more tabs by adding NavigationTab's to the Navigation Hub.
First, you need to create a new widget using Metro.
dart run nylo_framework:main make:stateful_widget create_advert_tab
// or with Metro
metro make:stateful_widget create_advert_tab
You can also create multiple widgets at once.
dart run nylo_framework:main make:stateful_widget news_tab,notifications_tab
// or with Metro
metro make:stateful_widget news_tab,notifications_tab
Then, you can add the new widget to the Navigation Hub.
_BaseNavigationHubState() : super(() async {
return {
0: NavigationTab(
title: "Home",
page: HomeTab(),
icon: Icon(Icons.home),
activeIcon: Icon(Icons.home),
),
1: NavigationTab(
title: "Settings",
page: SettingsTab(),
icon: Icon(Icons.settings),
activeIcon: Icon(Icons.settings),
),
2: NavigationTab(
title: "News",
page: NewsTab(),
icon: Icon(Icons.newspaper),
activeIcon: Icon(Icons.newspaper),
),
};
});
import 'package:nylo_framework/nylo_framework.dart';
appRouter() => nyRoutes((router) {
...
router.add(BaseNavigationHub.path).initalRoute();
});
// or navigate to the Navigation Hub from anywhere in your app
routeTo(BaseNavigationHub.path);
There's a lot more you can do with a Navigation Hub, let's dive into some of the features.
Bottom Navigation
You can change the layout to a bottom navigation bar by setting the layout to use NavigationHubLayout.bottomNav
.
class _MyNavigationHubState extends NavigationHub<MyNavigationHub> {
...
NavigationHubLayout? layout = NavigationHubLayout.bottomNav();
You can customize the bottom navigation bar by setting properties like the following:
class _MyNavigationHubState extends NavigationHub<MyNavigationHub> {
...
NavigationHubLayout? layout = NavigationHubLayout.bottomNav(
// customize the bottomNav layout properties
);
Top Navigation
You can change the layout to a top navigation bar by setting the layout to use NavigationHubLayout.topNav
.
class _MyNavigationHubState extends NavigationHub<MyNavigationHub> {
...
NavigationHubLayout? layout = NavigationHubLayout.topNav();
You can customize the top navigation bar by setting properties like the following:
class _MyNavigationHubState extends NavigationHub<MyNavigationHub> {
...
NavigationHubLayout? layout = NavigationHubLayout.topNav(
// customize the topNav layout properties
);
Journey Navigation
You can change the layout to a journey navigation by setting the layout to use NavigationHubLayout.journey
.
This is great for onboarding flows or multi-step forms.
class _MyNavigationHubState extends NavigationHub<MyNavigationHub> {
...
NavigationHubLayout? layout = NavigationHubLayout.journey(
// customize the journey layout properties
);
If you want to use the journey navigation layout, your widgets should use JourenyState
as it contains a lot of helper methods to help you manage the journey.
You can create a JourneyState using the below command.
dart run nylo_framework:main make:journey_widget welcome,phone_number_step,add_photos_step
// or with Metro
metro make:journey_widget welcome,phone_number_step,add_photos_step
This will create the following files in your resources/widgets/ directory welcome.dart
, phone_number_step.dart
and add_photos_step.dart
.
You can then add the new widgets to the Navigation Hub.
_MyNavigationHubState() : super(() async {
return {
0: NavigationTab.journey(
page: Welcome(),
),
1: NavigationTab.journey(
page: PhoneNumberStep(),
),
2: NavigationTab.journey(
page: AddPhotosStep(),
),
};
});
The journey navigation layout will automatically handle the back and next buttons for you if you define a buttonStyle
.
class _MyNavigationHubState extends NavigationHub<MyNavigationHub> {
...
NavigationHubLayout? layout = NavigationHubLayout.journey(
buttonStyle: JourneyButtonStyle.standard(
// Customize button properties
),
);
You can also customize the logic in your widgets.
import 'package:flutter/material.dart';
import '/resources/pages/onboarding_navigation_hub.dart';
import '/resources/widgets/buttons/buttons.dart';
import 'package:nylo_framework/nylo_framework.dart';
class WelcomeStep extends StatefulWidget {
const WelcomeStep({super.key});
@override
createState() => _WelcomeStepState();
}
class _WelcomeStepState extends JourneyState<WelcomeStep> {
_WelcomeStepState() : super(
navigationHubState: OnboardingNavigationHub.path.stateName());
@override
get init => () {
// Your initialization logic here
};
@override
Widget view(BuildContext context) {
return buildJourneyContent(
content: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('WelcomeStep', style: Theme.of(context).textTheme.headlineMedium),
const SizedBox(height: 20),
Text('This onboarding journey will help you get started.'),
],
),
nextButton: Button.primary(
text: isLastStep ? "Get Started" : "Continue",
onPressed: onNextPressed,
),
backButton: isFirstStep ? null : Button.textOnly(
text: "Back",
textColor: Colors.black87,
onPressed: onBackPressed,
),
);
}
/// Check if the journey can continue to the next step
/// Override this method to add validation logic
Future<bool> canContinue() async {
// Perform your validation logic here
// Return true if the journey can continue, false otherwise
return true;
}
/// Called when unable to continue (canContinue returns false)
/// Override this method to handle validation failures
Future<void> onCannotContinue() async {
showToastSorry(description: "You cannot continue");
}
/// Called before navigating to the next step
/// Override this method to perform actions before continuing
Future<void> onBeforeNext() async {
// E.g. save data here before navigating
}
/// Called after navigating to the next step
/// Override this method to perform actions after continuing
Future<void> onAfterNext() async {
// print('Navigated to the next step');
}
/// Called when the journey is complete (at the last step)
/// Override this method to perform completion actions
Future<void> onComplete() async {}
}
You can override any of the methods in the JourneyState
class.
Journey Progress Styles
You can customize the progress indicator style by using the JourneyProgressStyle
class.
class _MyNavigationHubState extends NavigationHub<MyNavigationHub> {
...
NavigationHubLayout? layout = NavigationHubLayout.journey(
progressStyle: JourneyProgressStyle.linear(
activeColor: Colors.blue,
inactiveColor: Colors.grey,
thickness: 4.0,
),
);
You can use the following progress styles:
-
JourneyProgressStyle.linear
: Linear progress indicator.
-
JourneyProgressStyle.dots
: Dots-based progress indicator.
-
JourneyProgressStyle.numbered
: Numbered step progress indicator.
-
JourneyProgressStyle.segments
: Segmented progress bar style.
-
JourneyProgressStyle.circular
: Circular progress indicator.
-
JourneyProgressStyle.timeline
: Timeline-style progress indicator.
-
JourneyProgressStyle.custom
: Custom progress indicator using a builder function.
class _MyNavigationHubState extends NavigationHub<MyNavigationHub> {
...
NavigationHubLayout? layout = NavigationHubLayout.journey(
progressStyle: JourneyProgressStyle.custom(
builder: (context, currentStep, totalSteps, percentage) {
return LinearProgressIndicator(
value: percentage,
backgroundColor: Colors.grey[200],
color: Colors.blue,
minHeight: 4.0,
);
},
),
);
You can also customize the progress indicator position by using the progressIndicatorPosition
property.
class _MyNavigationHubState extends NavigationHub<MyNavigationHub> {
...
NavigationHubLayout? layout = NavigationHubLayout.journey(
progressIndicatorPosition: ProgressIndicatorPosition.top,
);
You can use the following progress indicator positions:
-
ProgressIndicatorPosition.top
: Progress indicator at the top of the screen.
-
ProgressIndicatorPosition.bottom
: Progress indicator at the bottom of the screen.
You can also customize the progress indicator padding by using the progressIndicatorPadding
property.
class _MyNavigationHubState extends NavigationHub<MyNavigationHub> {
...
NavigationHubLayout? layout = NavigationHubLayout.journey(
progressIndicatorPadding: EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0),
);
Journey Button Styles
If you want to build an onboarding flow, you can set the buttonStyle
property in the NavigationHubLayout.journey
class.
Out the box, you can use the following button styles:
-
JourneyButtonStyle.standard
: Standard button style with customizable properties.
-
JourneyButtonStyle.minimal
: Minimal button style with icons only.
-
JourneyButtonStyle.outlined
: Outlined button style.
-
JourneyButtonStyle.contained
: Contained button style.
-
JourneyButtonStyle.custom
: Custom button style using builder functions.
class _MyNavigationHubState extends NavigationHub<MyNavigationHub> {
...
NavigationHubLayout? layout = NavigationHubLayout.journey(
progressStyle: JourneyProgressStyle.linear(),
buttonStyle: JourneyButtonStyle.standard(
// Customize button properties
),
);
JourneyState
The JourneyState
class contains a lot of helper methods to help you manage the journey.
To create a new JourneyState
, you can use the below command.
dart run nylo_framework:main make:journey_widget onboard_user_dob
Or if you want to create multiple widgets at once, you can use the following command.
dart run nylo_framework:main make:journey_widget welcome,phone_number_step,add_photos_step
This will create the following files in your resources/widgets/ directory welcome.dart
, phone_number_step.dart
and add_photos_step.dart
.
You can then add the new widgets to the Navigation Hub.
_MyNavigationHubState() : super(() async {
return {
0: NavigationTab.journey(
page: Welcome(),
),
1: NavigationTab.journey(
page: PhoneNumberStep(),
),
2: NavigationTab.journey(
page: AddPhotosStep(),
),
};
});
If we look at the WelcomeStep
class, we can see that it extends the JourneyState
class.
...
class _WelcomeTabState extends JourneyState<WelcomeTab> {
_WelcomeTabState() : super(
navigationHubState: BaseNavigationHub.path.stateName());
@override
get init => () {
// Your initialization logic here
};
@override
Widget view(BuildContext context) {
return buildJourneyContent(
progressStyle: JourneyProgressStyle.dots(
activeColor: Colors.red
),
content: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('WelcomeTab', style: Theme.of(context).textTheme.headlineMedium),
const SizedBox(height: 20),
Text('This onboarding journey will help you get started.'),
],
),
);
}
You'll notice that the JourneyState class will use buildJourneyContent
to build the content of the page.
Here are a list of the properties you can use in the buildJourneyContent
method.
Property |
Type |
Description |
content |
Widget |
The main content of the page. |
nextButton |
Widget? |
The next button widget. |
backButton |
Widget? |
The back button widget. |
progressPosition |
ProgressIndicatorPosition |
The position of the progress indicator. |
progressStyle |
JourneyProgressStyle? |
The style of the progress indicator. |
contentPadding |
EdgeInsetsGeometry |
The padding for the content. |
progressIndicatorPadding |
EdgeInsets? |
The padding for the progress indicator. |
header |
Widget? |
The header widget. |
footer |
Widget? |
The footer widget. |
crossAxisAlignment |
CrossAxisAlignment |
The cross axis alignment of the content. |
JourneyState Helper Methods
The JourneyState
class has some helper methods that you can use to customize the behavior of your journey.
onNextPressed
The onNextPressed
method is called when the next button is pressed.
E.g. You can use this method to trigger the next step in the journey.
@override
Widget view(BuildContext context) {
return buildJourneyContent(
content: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
...
],
),
nextButton: Button.primary(
text: isLastStep ? "Get Started" : "Continue",
onPressed: onNextPressed, // this will attempt to navigate to the next step
),
);
}
onBackPressed
The onBackPressed
method is called when the back button is pressed.
E.g. You can use this method to trigger the previous step in the journey.
@override
Widget view(BuildContext context) {
return buildJourneyContent(
content: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
...
],
),
backButton: isFirstStep ? null : Button.textOnly(
text: "Back",
textColor: Colors.black87,
onPressed: onBackPressed, // this will attempt to navigate to the previous step
),
);
}
onComplete
The onComplete
method is called when the journey is complete (at the last step).
E.g. if the if this widget is the last step in the journey, this method will be called.
Future<void> onComplete() async {
print("Journey completed");
}
onBeforeNext
The onBeforeNext
method is called before navigating to the next step.
E.g. if you want to save data before navigating to the next step, you can do it here.
Future<void> onBeforeNext() async {
// E.g. save data here before navigating
}
isFirstStep
The isFirstStep
method returns true if this is the first step in the journey.
E.g. You can use this method to disable the back button if this is the first step.
@override
Widget view(BuildContext context) {
return buildJourneyContent(
content: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
...
],
),
backButton: isFirstStep ? null : Button.textOnly( // Example of disabling the back button
text: "Back",
textColor: Colors.black87,
onPressed: onBackPressed,
),
);
}
isLastStep
The isLastStep
method returns true if this is the last step in the journey.
E.g. You can use this method to disable the next button if this is the last step.
@override
Widget view(BuildContext context) {
return buildJourneyContent(
content: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
...
],
),
nextButton: Button.primary(
text: isLastStep ? "Get Started" : "Continue", // Example updating the next button text
onPressed: onNextPressed,
),
);
}
goToStep
The goToStep
method is used to navigate to a specific step in the journey.
E.g. You can use this method to navigate to a specific step in the journey.
@override
Widget view(BuildContext context) {
return buildJourneyContent(
content: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
...
],
),
nextButton: Button.primary(
text: "Add photos"
onPressed: () {
goToStep(2); // this will navigate to the step with index 2
// Note: this will not trigger the onNextPressed method
},
),
);
}
goToNextStep
The goToNextStep
method is used to navigate to the next step in the journey.
E.g. You can use this method to navigate to the next step in the journey.
@override
Widget view(BuildContext context) {
return buildJourneyContent(
content: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
...
],
),
nextButton: Button.primary(
text: "Continue",
onPressed: () {
goToNextStep(); // this will navigate to the next step
// Note: this will not trigger the onNextPressed method
},
),
);
}
goToPreviousStep
The goToPreviousStep
method is used to navigate to the previous step in the journey.
E.g. You can use this method to navigate to the previous step in the journey.
@override
Widget view(BuildContext context) {
return buildJourneyContent(
content: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
...
],
),
backButton: isFirstStep ? null : Button.textOnly(
text: "Back",
textColor: Colors.black87,
onPressed: () {
goToPreviousStep(); // this will navigate to the previous step
},
),
);
}
onAfterNext
The onAfterNext
method is called after navigating to the next step.
E.g. if you want to perform some action after navigating to the next step, you can do it here.
Future<void> onAfterNext() async {
// print('Navigated to the next step');
}
onCannotContinue
The onCannotContinue
method is called when the journey cannot continue (canContinue returns false).
E.g. if you want to show an error message when the user tries to navigate to the next step without filling in the required fields, you can do it here.
Future<void> onCannotContinue() async {
showToastSorry(description: "You cannot continue");
}
canContinue
The canContinue
method is called when the user tries to navigate to the next step.
E.g. if you want to perform some validation before navigating to the next step, you can do it here.
Future<bool> canContinue() async {
// Perform your validation logic here
// Return true if the journey can continue, false otherwise
return true;
}
goToFirstStep
The goToFirstStep
method is used to navigate to the first step in the journey.
E.g. You can use this method to navigate to the first step in the journey.
@override
Widget view(BuildContext context) {
return buildJourneyContent(
content: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
...
],
),
nextButton: Button.primary(
text: "Continue",
onPressed: () {
goToFirstStep(); // this will navigate to the first step
},
),
);
}
goToLastStep
The goToLastStep
method is used to navigate to the last step in the journey.
E.g. You can use this method to navigate to the last step in the journey.
@override
Widget view(BuildContext context) {
return buildJourneyContent(
content: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
...
],
),
nextButton: Button.primary(
text: "Continue",
onPressed: () {
goToLastStep(); // this will navigate to the last step
},
),
);
}
Navigating to widgets within a tab
You can navigate to widgets within a tab by using the pushTo
helper.
Inside your tab, you can use the pushTo
helper to navigate to another widget.
_HomeTabState extends State<HomeTab> {
...
void _navigateToSettings() {
pushTo(SettingsPage());
}
...
}
You can also pass data to the widget you're navigating to.
_HomeTabState extends State<HomeTab> {
...
void _navigateToSettings() {
pushTo(SettingsPage(), data: {"name": "Anthony"});
}
...
}
Tabs
Tabs are the main building blocks of a Navigation Hub.
You can add tabs to a Navigation Hub by using the NavigationTab
class.
class _MyNavigationHubState extends NavigationHub<MyNavigationHub> {
...
NavigationHubLayout? layout = NavigationHubLayout.bottomNav();
...
_MyNavigationHubState() : super(() async {
return {
0: NavigationTab(
title: "Home",
page: HomeTab(),
icon: Icon(Icons.home),
activeIcon: Icon(Icons.home),
),
1: NavigationTab(
title: "Settings",
page: SettingsTab(),
icon: Icon(Icons.settings),
activeIcon: Icon(Icons.settings),
),
};
});
In the above example, we've added two tabs to the Navigation Hub, Home and Settings.
You can use different kinds of tabs like NavigationTab
, NavigationTab.badge
, and NavigationTab.alert
.
- The
NavigationTab.badge
class is used to add badges to tabs.
- The
NavigationTab.alert
class is used to add alerts to tabs.
- The
NavigationTab
class is used to add a normal tab.
Adding Badges to Tabs
We've made it easy to add badges to your tabs.
Badges are a great way to show users that there's something new in a tab.
Example, if you have a chat app, you can show the number of unread messages in the chat tab.
To add a badge to a tab, you can use the NavigationTab.badge
class.
class _MyNavigationHubState extends NavigationHub<MyNavigationHub> {
...
NavigationHubLayout? layout = NavigationHubLayout.bottomNav();
...
_MyNavigationHubState() : super(() async {
return {
0: NavigationTab.badge(
title: "Chats",
page: ChatTab(),
icon: Icon(Icons.message),
activeIcon: Icon(Icons.message),
initialCount: 10,
),
1: NavigationTab(
title: "Settings",
page: SettingsTab(),
icon: Icon(Icons.settings),
activeIcon: Icon(Icons.settings),
),
};
});
In the above example, we've added a badge to the Chat tab with an initial count of 10.
You can also update the badge count programmatically.
/// Increment the badge count
BaseNavigationHub.stateActions.incrementBadgeCount(tab: 0);
/// Update the badge count
BaseNavigationHub.stateActions.updateBadgeCount(tab: 0, count: 5);
/// Clear the badge count
BaseNavigationHub.stateActions.clearBadgeCount(tab: 0);
By default, the badge count will be remembered. If you want to clear the badge count each session, you can set rememberCount
to false
.
class _MyNavigationHubState extends NavigationHub<MyNavigationHub> {
...
NavigationHubLayout? layout = NavigationHubLayout.bottomNav();
...
_MyNavigationHubState() : super(() async {
return {
0: NavigationTab.badge(
title: "Chats",
page: ChatTab(),
icon: Icon(Icons.message),
activeIcon: Icon(Icons.message),
initialCount: 10,
rememberCount: false,
),
1: NavigationTab(
title: "Settings",
page: SettingsTab(),
icon: Icon(Icons.settings),
activeIcon: Icon(Icons.settings),
),
};
});
Adding Alerts to Tabs
You can add alerts to your tabs.
Sometime you might not want to show a badge count, but you want to show an alert to the user.
To add an alert to a tab, you can use the NavigationTab.alert
class.
class _MyNavigationHubState extends NavigationHub<MyNavigationHub> {
...
NavigationHubLayout? layout = NavigationHubLayout.bottomNav();
...
_MyNavigationHubState() : super(() async {
return {
0: NavigationTab.alert(
title: "Chats",
page: ChatTab(),
icon: Icon(Icons.message),
activeIcon: Icon(Icons.message),
alertColor: Colors.red,
alertEnabled: true,
rememberAlert: false,
),
1: NavigationTab(
title: "Settings",
page: SettingsTab(),
icon: Icon(Icons.settings),
activeIcon: Icon(Icons.settings),
),
};
});
This will add an alert to the Chat tab with a red color.
You can also update the alert programmatically.
/// Enable the alert
BaseNavigationHub.stateActions.alertEnableTab(tab: 0);
/// Disable the alert
BaseNavigationHub.stateActions.alertDisableTab(tab: 0);
Maintaining state
By default, the state of the Navigation Hub is maintained.
This means that when you navigate to a tab, the state of the tab is preserved.
If you want to clear the state of the tab each time you navigate to it, you can set maintainState
to false
.
class _MyNavigationHubState extends NavigationHub<MyNavigationHub> {
...
@override
bool get maintainState => false;
...
}
State Actions
State actions are a way to interact with the Navigation Hub from anywhere in your app.
Here are some of the state actions you can use:
/// Reset the tab
/// E.g. MyNavigationHub.stateActions.resetTabState(tab: 0);
resetTabState({required tab});
/// Update the badge count
/// E.g. MyNavigationHub.updateBadgeCount(tab: 0, count: 2);
updateBadgeCount({required int tab, required int count});
/// Increment the badge count
/// E.g. MyNavigationHub.incrementBadgeCount(tab: 0);
incrementBadgeCount({required int tab});
/// Clear the badge count
/// E.g. MyNavigationHub.clearBadgeCount(tab: 0);
clearBadgeCount({required int tab});
To use a state action, you can do the following:
MyNavigationHub.stateActions.updateBadgeCount(tab: 0, count: 2);
// or
MyNavigationHub.stateActions.resetTabState(tab: 0);
Loading Style
Out the box, the Navigation Hub will show your default loading Widget (resources/widgets/loader_widget.dart) when the tab is loading.
You can customize the loadingStyle
to update the loading style.
Here's a table for the different loading styles you can use:
// normal, skeletonizer, none
Style |
Description |
normal |
Default loading style |
skeletonizer |
Skeleton loading style |
none |
No loading style |
You can change the loading style like this:
@override
LoadingStyle get loadingStyle => LoadingStyle.normal();
// or
@override
LoadingStyle get loadingStyle => LoadingStyle.skeletonizer();
If you want to update the loading Widget in one of the styles, you can pass a child
to the LoadingStyle
.
@override
LoadingStyle get loadingStyle => LoadingStyle.normal(
child: Center(
child: Text("Loading..."),
),
);
Now, when the tab is loading, the text "Loading..." will be displayed.
Example below:
class _MyNavigationHubState extends NavigationHub<MyNavigationHub> {
...
_BaseNavigationHubState() : super(() async {
await sleep(3); // simulate loading for 3 seconds
return {
0: NavigationTab(
title: "Home",
page: HomeTab(),
icon: Icon(Icons.home),
activeIcon: Icon(Icons.home),
),
1: NavigationTab(
title: "Settings",
page: SettingsTab(),
icon: Icon(Icons.settings),
activeIcon: Icon(Icons.settings),
),
};
});
@override
LoadingStyle get loadingStyle => LoadingStyle.normal(
child: Center(
child: Text("Loading..."),
),
);
...
}
Creating a Navigation Hub
To create a Navigation Hub, you can use Metro, use the below command.
metro make:navigation_hub base
This will create a base_navigation_hub.dart file in your resources/pages/
directory and add the Navigation Hub to your routes/router.dart
file.