Navigation Hub
Pengantar
Navigation Hub adalah tempat sentral di mana Anda dapat mengelola navigasi untuk semua widget Anda. Secara langsung, Anda dapat membuat tata letak navigasi bawah, atas, dan journey dalam hitungan detik.
Mari bayangkan Anda memiliki aplikasi dan ingin menambahkan navigasi bar bawah serta memungkinkan pengguna berpindah antar tab di aplikasi Anda.
Anda dapat menggunakan Navigation Hub untuk membangun ini.
Mari kita lihat bagaimana cara menggunakan Navigation Hub di aplikasi Anda.
Penggunaan Dasar
Anda dapat membuat Navigation Hub menggunakan perintah di bawah ini.
metro make:navigation_hub base
Perintah ini akan memandu Anda melalui pengaturan interaktif:
- Pilih tipe layout - Pilih antara
navigation_tabs(navigasi bawah) ataujourney_states(alur berurutan). - Masukkan nama tab/state - Berikan nama-nama yang dipisahkan koma untuk tab atau journey state Anda.
Ini akan membuat file di direktori resources/pages/navigation_hubs/base/ Anda:
base_navigation_hub.dart- Widget hub utamatabs/ataustates/- Berisi widget anak untuk setiap tab atau journey state
Berikut tampilan Navigation Hub yang dihasilkan:
import 'package:flutter/material.dart';
import 'package:nylo_framework/nylo_framework.dart';
import '/resources/pages/navigation_hubs/base/tabs/home_tab_widget.dart';
import '/resources/pages/navigation_hubs/base/tabs/settings_tab_widget.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> {
/// Layout builder
@override
NavigationHubLayout? layout(BuildContext context) => NavigationHubLayout.bottomNav();
/// Should the state be maintained
@override
bool get maintainState => true;
/// The initial index
@override
int get initialIndex => 0;
/// Navigation pages
_BaseNavigationHubState() : super(() => {
0: NavigationTab.tab(title: "Home", page: HomeTab()),
1: NavigationTab.tab(title: "Settings", page: SettingsTab()),
});
/// Handle the tap event
@override
onTap(int index) {
super.onTap(index);
}
}
Anda dapat melihat bahwa Navigation Hub memiliki dua tab, Home dan Settings.
Method layout mengembalikan tipe layout untuk hub. Method ini menerima BuildContext sehingga Anda dapat mengakses data tema dan media query saat mengonfigurasi layout Anda.
Anda dapat membuat lebih banyak tab dengan menambahkan NavigationTab ke Navigation Hub.
Pertama, Anda perlu membuat widget baru menggunakan Metro.
metro make:stateful_widget news_tab
Anda juga dapat membuat beberapa widget sekaligus.
metro make:stateful_widget news_tab,notifications_tab
Kemudian, Anda dapat menambahkan widget baru ke Navigation Hub.
_BaseNavigationHubState() : super(() => {
0: NavigationTab.tab(title: "Home", page: HomeTab()),
1: NavigationTab.tab(title: "Settings", page: SettingsTab()),
2: NavigationTab.tab(title: "News", page: NewsTab()),
});
Untuk menggunakan Navigation Hub, tambahkan ke router Anda sebagai rute awal:
import 'package:nylo_framework/nylo_framework.dart';
appRouter() => nyRoutes((router) {
...
router.add(BaseNavigationHub.path).initialRoute();
});
// or navigate to the Navigation Hub from anywhere in your app
routeTo(BaseNavigationHub.path);
Masih banyak lagi yang dapat Anda lakukan dengan Navigation Hub, mari kita bahas beberapa fiturnya.
Navigasi Bawah
Anda dapat mengatur layout menjadi navigasi bar bawah dengan mengembalikan NavigationHubLayout.bottomNav dari method layout.
class _MyNavigationHubState extends NavigationHub<MyNavigationHub> {
...
@override
NavigationHubLayout? layout(BuildContext context) => NavigationHubLayout.bottomNav();
Anda dapat menyesuaikan navigasi bar bawah dengan mengatur properti seperti berikut:
class _MyNavigationHubState extends NavigationHub<MyNavigationHub> {
...
@override
NavigationHubLayout? layout(BuildContext context) => NavigationHubLayout.bottomNav(
backgroundColor: Colors.white,
selectedItemColor: Colors.blue,
unselectedItemColor: Colors.grey,
elevation: 8.0,
iconSize: 24.0,
selectedFontSize: 14.0,
unselectedFontSize: 12.0,
showSelectedLabels: true,
showUnselectedLabels: true,
type: BottomNavigationBarType.fixed,
);
Anda dapat menerapkan gaya preset ke navigasi bar bawah Anda menggunakan parameter style.
@override
NavigationHubLayout? layout(BuildContext context) => NavigationHubLayout.bottomNav(
style: BottomNavStyle.material(), // Default Flutter material style
);
Nav Bar Builder Kustom
Untuk kontrol penuh atas navigasi bar Anda, Anda dapat menggunakan parameter navBarBuilder.
Ini memungkinkan Anda membangun widget kustom apa pun sambil tetap menerima data navigasi.
class _MyNavigationHubState extends NavigationHub<MyNavigationHub> {
...
@override
NavigationHubLayout? layout(BuildContext context) => NavigationHubLayout.bottomNav(
navBarBuilder: (context, data) {
return MyCustomNavBar(
items: data.items,
currentIndex: data.currentIndex,
onTap: data.onTap,
);
},
);
Objek NavBarData berisi:
| Properti | Tipe | Deskripsi |
|---|---|---|
items |
List<BottomNavigationBarItem> |
Item navigasi bar |
currentIndex |
int |
Indeks yang sedang dipilih |
onTap |
ValueChanged<int> |
Callback saat tab diketuk |
Berikut contoh navigasi bar glass kustom sepenuhnya:
NavigationHubLayout.bottomNav(
navBarBuilder: (context, data) {
return Padding(
padding: EdgeInsets.all(16),
child: ClipRRect(
borderRadius: BorderRadius.circular(25),
child: BackdropFilter(
filter: ImageFilter.blur(sigmaX: 10, sigmaY: 10),
child: Container(
decoration: BoxDecoration(
color: Colors.white.withValues(alpha: 0.7),
borderRadius: BorderRadius.circular(25),
),
child: BottomNavigationBar(
items: data.items,
currentIndex: data.currentIndex,
onTap: data.onTap,
backgroundColor: Colors.transparent,
elevation: 0,
),
),
),
),
);
},
)
Catatan: Saat menggunakan
navBarBuilder, parameterstyleakan diabaikan.
Navigasi Atas
Anda dapat mengubah layout menjadi navigasi bar atas dengan mengembalikan NavigationHubLayout.topNav dari method layout.
class _MyNavigationHubState extends NavigationHub<MyNavigationHub> {
...
@override
NavigationHubLayout? layout(BuildContext context) => NavigationHubLayout.topNav();
Anda dapat menyesuaikan navigasi bar atas dengan mengatur properti seperti berikut:
class _MyNavigationHubState extends NavigationHub<MyNavigationHub> {
...
@override
NavigationHubLayout? layout(BuildContext context) => NavigationHubLayout.topNav(
backgroundColor: Colors.white,
labelColor: Colors.blue,
unselectedLabelColor: Colors.grey,
indicatorColor: Colors.blue,
indicatorWeight: 3.0,
isScrollable: false,
hideAppBarTitle: true,
);
Navigasi Journey
Anda dapat mengubah layout menjadi navigasi journey dengan mengembalikan NavigationHubLayout.journey dari method layout.
Ini sangat cocok untuk alur onboarding atau form multi-langkah.
class _MyNavigationHubState extends NavigationHub<MyNavigationHub> {
...
@override
NavigationHubLayout? layout(BuildContext context) => NavigationHubLayout.journey(
progressStyle: JourneyProgressStyle(
indicator: JourneyProgressIndicator.segments(),
),
);
Anda juga dapat mengatur backgroundGradient untuk layout journey:
@override
NavigationHubLayout? layout(BuildContext context) => NavigationHubLayout.journey(
backgroundGradient: LinearGradient(
colors: [Colors.blue, Colors.purple],
begin: Alignment.topLeft,
end: Alignment.bottomRight,
),
progressStyle: JourneyProgressStyle(
indicator: JourneyProgressIndicator.linear(),
),
);
Catatan: Ketika
backgroundGradientdiatur, ia akan lebih diprioritaskan daripadabackgroundColor.
Jika Anda ingin menggunakan layout navigasi journey, widget Anda sebaiknya menggunakan JourneyState karena berisi banyak method helper untuk membantu Anda mengelola journey.
Anda dapat membuat seluruh journey menggunakan perintah make:navigation_hub dengan layout journey_states:
metro make:navigation_hub onboarding
# Select: journey_states
# Enter: welcome, personal_info, add_photos
Ini akan membuat hub dan semua widget journey state di resources/pages/navigation_hubs/onboarding/states/.
Atau Anda dapat membuat widget journey individual menggunakan:
metro make:journey_widget welcome,phone_number_step,add_photos_step
Anda kemudian dapat menambahkan widget baru ke Navigation Hub.
_MyNavigationHubState() : super(() => {
0: NavigationTab.journey(
page: Welcome(),
),
1: NavigationTab.journey(
page: PhoneNumberStep(),
),
2: NavigationTab.journey(
page: AddPhotosStep(),
),
});
Gaya Progress Journey
Anda dapat menyesuaikan gaya indikator progress menggunakan kelas JourneyProgressStyle.
class _MyNavigationHubState extends NavigationHub<MyNavigationHub> {
...
@override
NavigationHubLayout? layout(BuildContext context) => NavigationHubLayout.journey(
progressStyle: JourneyProgressStyle(
indicator: JourneyProgressIndicator.linear(
activeColor: Colors.blue,
inactiveColor: Colors.grey,
thickness: 4.0,
),
),
);
Anda dapat menggunakan indikator progress berikut:
JourneyProgressIndicator.none(): Tidak merender apa pun - berguna untuk menyembunyikan indikator pada tab tertentu.JourneyProgressIndicator.linear(): Indikator progress linear.JourneyProgressIndicator.dots(): Indikator progress berbasis titik.JourneyProgressIndicator.numbered(): Indikator progress langkah bernomor.JourneyProgressIndicator.segments(): Gaya progress bar tersegmentasi.JourneyProgressIndicator.circular(): Indikator progress melingkar.JourneyProgressIndicator.timeline(): Indikator progress gaya timeline.JourneyProgressIndicator.custom(): Indikator progress kustom menggunakan fungsi builder.
@override
NavigationHubLayout? layout(BuildContext context) => NavigationHubLayout.journey(
progressStyle: JourneyProgressStyle(
indicator: JourneyProgressIndicator.custom(
builder: (context, currentStep, totalSteps, percentage) {
return LinearProgressIndicator(
value: percentage,
backgroundColor: Colors.grey[200],
color: Colors.blue,
minHeight: 4.0,
);
},
),
),
);
Anda dapat menyesuaikan posisi dan padding indikator progress di dalam JourneyProgressStyle:
@override
NavigationHubLayout? layout(BuildContext context) => NavigationHubLayout.journey(
progressStyle: JourneyProgressStyle(
indicator: JourneyProgressIndicator.dots(),
position: ProgressIndicatorPosition.bottom,
padding: EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0),
),
);
Anda dapat menggunakan posisi indikator progress berikut:
ProgressIndicatorPosition.top: Indikator progress di bagian atas layar.ProgressIndicatorPosition.bottom: Indikator progress di bagian bawah layar.
Override Gaya Progress Per-Tab
Anda dapat meng-override progressStyle pada level layout untuk tab individual menggunakan NavigationTab.journey(progressStyle: ...). Tab tanpa progressStyle sendiri akan mewarisi default layout. Tab tanpa default layout dan tanpa gaya per-tab tidak akan menampilkan indikator progress.
_MyNavigationHubState() : super(() => {
0: NavigationTab.journey(
page: Welcome(),
),
1: NavigationTab.journey(
page: PhoneNumberStep(),
progressStyle: JourneyProgressStyle(
indicator: JourneyProgressIndicator.numbered(),
), // overrides the layout default for this tab only
),
2: NavigationTab.journey(
page: AddPhotosStep(),
),
});
JourneyState
Kelas JourneyState meng-extend NyState dengan fungsionalitas khusus journey untuk mempermudah pembuatan alur onboarding dan journey multi-langkah.
Untuk membuat JourneyState baru, Anda dapat menggunakan perintah di bawah ini.
metro make:journey_widget onboard_user_dob
Atau jika Anda ingin membuat beberapa widget sekaligus, Anda dapat menggunakan perintah berikut.
metro make:journey_widget welcome,phone_number_step,add_photos_step
Berikut tampilan widget JourneyState yang dihasilkan:
import 'package:flutter/material.dart';
import '/resources/pages/navigation_hubs/onboarding/onboarding_navigation_hub.dart';
import '/resources/widgets/buttons/buttons.dart';
import 'package:nylo_framework/nylo_framework.dart';
class Welcome extends StatefulWidget {
const Welcome({super.key});
@override
createState() => _WelcomeState();
}
class _WelcomeState extends JourneyState<Welcome> {
_WelcomeState() : super(
navigationHubState: OnboardingNavigationHub.path.stateName());
@override
get init => () {
// Your initialization logic here
};
@override
Widget view(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(16),
child: Column(
children: [
Expanded(
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('Welcome', style: Theme.of(context).textTheme.headlineMedium),
const SizedBox(height: 20),
Text('This onboarding journey will help you get started.'),
],
),
),
),
// Navigation buttons
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
if (!isFirstStep)
Flexible(
child: Button.textOnly(
text: "Back",
textColor: Colors.black87,
onPressed: onBackPressed,
),
)
else
const SizedBox.shrink(),
Flexible(
child: Button.primary(
text: "Continue",
onPressed: nextStep,
),
),
],
),
],
),
);
}
/// Check if the journey can continue to the next step
@override
Future<bool> canContinue() async {
return true;
}
/// Called before navigating to the next step
@override
Future<void> onBeforeNext() async {
// E.g. save data to session
}
/// Called when the journey is complete (at the last step)
@override
Future<void> onComplete() async {}
}
Anda akan melihat bahwa kelas JourneyState menggunakan nextStep untuk berpindah maju dan onBackPressed untuk kembali.
Method nextStep menjalankan seluruh siklus validasi: canContinue() -> onBeforeNext() -> navigasi (atau onComplete() jika di langkah terakhir) -> onAfterNext().
Anda juga dapat menggunakan buildJourneyContent untuk membangun layout terstruktur dengan tombol navigasi opsional:
@override
Widget view(BuildContext context) {
return buildJourneyContent(
content: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('Welcome', 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: nextStep,
),
backButton: isFirstStep ? null : Button.textOnly(
text: "Back",
textColor: Colors.black87,
onPressed: onBackPressed,
),
);
}
Berikut properti yang dapat Anda gunakan di method buildJourneyContent.
| Properti | Tipe | Deskripsi |
|---|---|---|
content |
Widget |
Konten utama halaman. |
nextButton |
Widget? |
Widget tombol lanjut. |
backButton |
Widget? |
Widget tombol kembali. |
contentPadding |
EdgeInsetsGeometry |
Padding untuk konten. |
header |
Widget? |
Widget header. |
footer |
Widget? |
Widget footer. |
crossAxisAlignment |
CrossAxisAlignment |
Alignment sumbu silang konten. |
Method Helper JourneyState
Kelas JourneyState memiliki method helper dan properti yang dapat Anda gunakan untuk menyesuaikan perilaku journey Anda.
| Method / Properti | Deskripsi |
|---|---|
nextStep() |
Berpindah ke langkah berikutnya dengan validasi. Mengembalikan Future<bool>. |
previousStep() |
Berpindah ke langkah sebelumnya. Mengembalikan Future<bool>. |
onBackPressed() |
Helper sederhana untuk berpindah ke langkah sebelumnya. |
onComplete() |
Dipanggil saat journey selesai (di langkah terakhir). |
onBeforeNext() |
Dipanggil sebelum berpindah ke langkah berikutnya. |
onAfterNext() |
Dipanggil setelah berpindah ke langkah berikutnya. |
canContinue() |
Pengecekan validasi sebelum berpindah ke langkah berikutnya. |
isFirstStep |
Mengembalikan true jika ini adalah langkah pertama dalam journey. |
isLastStep |
Mengembalikan true jika ini adalah langkah terakhir dalam journey. |
currentStep |
Mengembalikan indeks langkah saat ini (berbasis 0). |
totalSteps |
Mengembalikan jumlah total langkah. |
completionPercentage |
Mengembalikan persentase penyelesaian (0.0 hingga 1.0). |
goToStep(int index) |
Langsung menuju langkah tertentu berdasarkan indeks. |
goToNextStep() |
Langsung menuju langkah berikutnya (tanpa validasi). |
goToPreviousStep() |
Langsung menuju langkah sebelumnya (tanpa validasi). |
goToFirstStep() |
Langsung menuju langkah pertama. |
goToLastStep() |
Langsung menuju langkah terakhir. |
exitJourney() |
Keluar dari journey dengan melakukan pop pada root navigator. |
resetCurrentStep() |
Mereset state langkah saat ini. |
onJourneyComplete |
Callback saat journey selesai (override di langkah terakhir). |
buildJourneyPage() |
Membangun halaman journey layar penuh dengan Scaffold. |
nextStep
Method nextStep berpindah ke langkah berikutnya dengan validasi penuh. Method ini menjalankan siklus: canContinue() -> onBeforeNext() -> navigasi atau onComplete() -> onAfterNext().
Anda dapat memasukkan force: true untuk melewati validasi dan langsung berpindah.
@override
Widget view(BuildContext context) {
return buildJourneyContent(
content: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
...
],
),
nextButton: Button.primary(
text: isLastStep ? "Get Started" : "Continue",
onPressed: nextStep, // runs validation then navigates
),
);
}
Untuk melewati validasi:
onPressed: () => nextStep(force: true),
previousStep
Method previousStep berpindah ke langkah sebelumnya. Mengembalikan true jika berhasil, false jika sudah di langkah pertama.
onPressed: () async {
bool success = await previousStep();
if (!success) {
// Already at first step
}
},
onBackPressed
Method onBackPressed adalah helper sederhana yang memanggil previousStep() secara internal.
@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,
),
);
}
onComplete
Method onComplete dipanggil saat nextStep() dipicu di langkah terakhir (setelah validasi berhasil).
@override
Future<void> onComplete() async {
print("Journey completed");
}
onBeforeNext
Method onBeforeNext dipanggil sebelum berpindah ke langkah berikutnya.
Contoh: jika Anda ingin menyimpan data sebelum berpindah ke langkah berikutnya, Anda dapat melakukannya di sini.
@override
Future<void> onBeforeNext() async {
// E.g. save data to session
// session('onboarding', {
// 'name': 'Anthony Gordon',
// 'occupation': 'Software Engineer',
// });
}
onAfterNext
Method onAfterNext dipanggil setelah berpindah ke langkah berikutnya.
@override
Future<void> onAfterNext() async {
// print('Navigated to the next step');
}
canContinue
Method canContinue dipanggil saat nextStep() dipicu. Kembalikan false untuk mencegah navigasi.
@override
Future<bool> canContinue() async {
// Perform your validation logic here
// Return true if the journey can continue, false otherwise
if (nameController.text.isEmpty) {
showToastSorry(description: "Please enter your name");
return false;
}
return true;
}
isFirstStep
Properti isFirstStep mengembalikan true jika ini adalah langkah pertama dalam journey.
backButton: isFirstStep ? null : Button.textOnly(
text: "Back",
textColor: Colors.black87,
onPressed: onBackPressed,
),
isLastStep
Properti isLastStep mengembalikan true jika ini adalah langkah terakhir dalam journey.
nextButton: Button.primary(
text: isLastStep ? "Get Started" : "Continue",
onPressed: nextStep,
),
currentStep
Properti currentStep mengembalikan indeks langkah saat ini (berbasis 0).
Text("Step ${currentStep + 1} of $totalSteps"),
totalSteps
Properti totalSteps mengembalikan jumlah total langkah dalam journey.
completionPercentage
Properti completionPercentage mengembalikan persentase penyelesaian sebagai nilai dari 0.0 hingga 1.0.
LinearProgressIndicator(value: completionPercentage),
goToStep
Method goToStep langsung menuju langkah tertentu berdasarkan indeks. Method ini tidak memicu validasi.
nextButton: Button.primary(
text: "Skip to photos",
onPressed: () {
goToStep(2); // jump to step index 2
},
),
goToNextStep
Method goToNextStep langsung menuju langkah berikutnya tanpa validasi. Jika sudah di langkah terakhir, method ini tidak melakukan apa-apa.
onPressed: () {
goToNextStep(); // skip validation and go to next step
},
goToPreviousStep
Method goToPreviousStep langsung menuju langkah sebelumnya tanpa validasi. Jika sudah di langkah pertama, method ini tidak melakukan apa-apa.
onPressed: () {
goToPreviousStep();
},
goToFirstStep
Method goToFirstStep langsung menuju langkah pertama.
onPressed: () {
goToFirstStep();
},
goToLastStep
Method goToLastStep langsung menuju langkah terakhir.
onPressed: () {
goToLastStep();
},
exitJourney
Method exitJourney keluar dari journey dengan melakukan pop pada root navigator.
onPressed: () {
exitJourney(); // pop the root navigator
},
resetCurrentStep
Method resetCurrentStep mereset state langkah saat ini.
onPressed: () {
resetCurrentStep();
},
onJourneyComplete
Getter onJourneyComplete dapat di-override di langkah terakhir journey Anda untuk menentukan apa yang terjadi saat pengguna menyelesaikan alur tersebut.
class _CompleteStepState extends JourneyState<CompleteStep> {
_CompleteStepState() : super(
navigationHubState: OnboardingNavigationHub.path.stateName());
/// Callback when journey completes
@override
void Function()? get onJourneyComplete => () {
// Navigate to your home page or next destination
routeTo(HomePage.path);
};
@override
Widget view(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(16),
child: Column(
children: [
...
Button.primary(
text: "Get Started",
onPressed: onJourneyComplete, // triggers the completion callback
),
],
),
);
}
}
buildJourneyPage
Method buildJourneyPage membangun halaman journey layar penuh yang dibungkus dalam Scaffold dengan SafeArea.
@override
Widget view(BuildContext context) {
return buildJourneyPage(
content: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('Welcome', style: Theme.of(context).textTheme.headlineMedium),
],
),
nextButton: Button.primary(
text: "Continue",
onPressed: nextStep,
),
backgroundColor: Colors.white,
);
}
| Properti | Tipe | Deskripsi |
|---|---|---|
content |
Widget |
Konten utama halaman. |
nextButton |
Widget? |
Widget tombol lanjut. |
backButton |
Widget? |
Widget tombol kembali. |
contentPadding |
EdgeInsetsGeometry |
Padding untuk konten. |
header |
Widget? |
Widget header. |
footer |
Widget? |
Widget footer. |
backgroundColor |
Color? |
Warna latar belakang Scaffold. |
appBar |
Widget? |
Widget AppBar opsional. |
crossAxisAlignment |
CrossAxisAlignment |
Alignment sumbu silang konten. |
Navigasi ke widget di dalam tab
Anda dapat berpindah ke widget di dalam tab menggunakan helper pushTo.
Di dalam tab Anda, Anda dapat menggunakan helper pushTo untuk berpindah ke widget lain.
_HomeTabState extends State<HomeTab> {
...
void _navigateToSettings() {
pushTo(SettingsPage());
}
...
}
Anda juga dapat mengirim data ke widget yang Anda tuju.
_HomeTabState extends State<HomeTab> {
...
void _navigateToSettings() {
pushTo(SettingsPage(), data: {"name": "Anthony"});
}
...
}
Tab
Tab adalah blok bangunan utama dari Navigation Hub.
Anda dapat menambahkan tab ke Navigation Hub menggunakan kelas NavigationTab dan named constructor-nya.
class _MyNavigationHubState extends NavigationHub<MyNavigationHub> {
...
@override
NavigationHubLayout? layout(BuildContext context) => NavigationHubLayout.bottomNav();
...
_MyNavigationHubState() : super(() => {
0: NavigationTab.tab(
title: "Home",
page: HomeTab(),
icon: Icon(Icons.home),
activeIcon: Icon(Icons.home),
),
1: NavigationTab.tab(
title: "Settings",
page: SettingsTab(),
icon: Icon(Icons.settings),
activeIcon: Icon(Icons.settings),
),
});
Pada contoh di atas, kita menambahkan dua tab ke Navigation Hub, Home dan Settings.
Anda dapat menggunakan berbagai jenis tab:
NavigationTab.tab()- Tab navigasi standar.NavigationTab.badge()- Tab dengan jumlah badge.NavigationTab.alert()- Tab dengan indikator alert.NavigationTab.journey()- Tab untuk layout navigasi journey.
Menambahkan Badge ke Tab
Kami telah memudahkan untuk menambahkan badge ke tab Anda.
Badge adalah cara yang bagus untuk menunjukkan kepada pengguna bahwa ada sesuatu yang baru di suatu tab.
Contohnya, jika Anda memiliki aplikasi chat, Anda dapat menampilkan jumlah pesan yang belum dibaca di tab chat.
Untuk menambahkan badge ke tab, Anda dapat menggunakan constructor NavigationTab.badge.
class _MyNavigationHubState extends NavigationHub<MyNavigationHub> {
...
@override
NavigationHubLayout? layout(BuildContext context) => NavigationHubLayout.bottomNav();
...
_MyNavigationHubState() : super(() => {
0: NavigationTab.badge(
title: "Chats",
page: ChatTab(),
icon: Icon(Icons.message),
activeIcon: Icon(Icons.message),
initialCount: 10,
),
1: NavigationTab.tab(
title: "Settings",
page: SettingsTab(),
icon: Icon(Icons.settings),
activeIcon: Icon(Icons.settings),
),
});
Pada contoh di atas, kita menambahkan badge ke tab Chat dengan jumlah awal 10.
Anda juga dapat memperbarui jumlah badge secara programatis.
/// 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);
Secara default, jumlah badge akan diingat. Jika Anda ingin menghapus jumlah badge setiap sesi, Anda dapat mengatur rememberCount ke false.
0: NavigationTab.badge(
title: "Chats",
page: ChatTab(),
icon: Icon(Icons.message),
activeIcon: Icon(Icons.message),
initialCount: 10,
rememberCount: false,
),
Menambahkan Alert ke Tab
Anda dapat menambahkan alert ke tab Anda.
Terkadang Anda mungkin tidak ingin menampilkan jumlah badge, tetapi ingin menampilkan indikator alert kepada pengguna.
Untuk menambahkan alert ke tab, Anda dapat menggunakan constructor NavigationTab.alert.
class _MyNavigationHubState extends NavigationHub<MyNavigationHub> {
...
@override
NavigationHubLayout? layout(BuildContext context) => NavigationHubLayout.bottomNav();
...
_MyNavigationHubState() : super(() => {
0: NavigationTab.alert(
title: "Chats",
page: ChatTab(),
icon: Icon(Icons.message),
activeIcon: Icon(Icons.message),
alertColor: Colors.red,
alertEnabled: true,
rememberAlert: false,
),
1: NavigationTab.tab(
title: "Settings",
page: SettingsTab(),
icon: Icon(Icons.settings),
activeIcon: Icon(Icons.settings),
),
});
Ini akan menambahkan alert ke tab Chat dengan warna merah.
Anda juga dapat memperbarui alert secara programatis.
/// Enable the alert
BaseNavigationHub.stateActions.alertEnableTab(tab: 0);
/// Disable the alert
BaseNavigationHub.stateActions.alertDisableTab(tab: 0);
Indeks Awal
Secara default, Navigation Hub dimulai dari tab pertama (indeks 0). Anda dapat mengubahnya dengan meng-override getter initialIndex.
class _MyNavigationHubState extends NavigationHub<MyNavigationHub> {
...
@override
int get initialIndex => 1; // Start on the second tab
...
}
Mempertahankan State
Secara default, state Navigation Hub dipertahankan.
Ini berarti saat Anda berpindah ke tab, state tab tersebut akan dipertahankan.
Jika Anda ingin menghapus state tab setiap kali berpindah ke sana, Anda dapat mengatur maintainState ke false.
class _MyNavigationHubState extends NavigationHub<MyNavigationHub> {
...
@override
bool get maintainState => false;
...
}
onTap
Anda dapat meng-override method onTap untuk menambahkan logika kustom saat sebuah tab diketuk.
class _MyNavigationHubState extends NavigationHub<MyNavigationHub> {
...
@override
onTap(int index) {
// Add custom logic here
// E.g. track analytics, show confirmation, etc.
super.onTap(index); // Always call super to handle the tab switch
}
}
Aksi State
Aksi state adalah cara untuk berinteraksi dengan Navigation Hub dari mana saja di aplikasi Anda.
Berikut aksi state yang dapat Anda gunakan:
/// Reset the tab at a given index
/// E.g. MyNavigationHub.stateActions.resetTabIndex(0);
resetTabIndex(int tabIndex);
/// Change the current tab programmatically
/// E.g. MyNavigationHub.stateActions.currentTabIndex(2);
currentTabIndex(int tabIndex);
/// Update the badge count
/// E.g. MyNavigationHub.stateActions.updateBadgeCount(tab: 0, count: 2);
updateBadgeCount({required int tab, required int count});
/// Increment the badge count
/// E.g. MyNavigationHub.stateActions.incrementBadgeCount(tab: 0);
incrementBadgeCount({required int tab});
/// Clear the badge count
/// E.g. MyNavigationHub.stateActions.clearBadgeCount(tab: 0);
clearBadgeCount({required int tab});
/// Enable the alert for a tab
/// E.g. MyNavigationHub.stateActions.alertEnableTab(tab: 0);
alertEnableTab({required int tab});
/// Disable the alert for a tab
/// E.g. MyNavigationHub.stateActions.alertDisableTab(tab: 0);
alertDisableTab({required int tab});
/// Navigate to the next page in a journey layout
/// E.g. await MyNavigationHub.stateActions.nextPage();
Future<bool> nextPage();
/// Navigate to the previous page in a journey layout
/// E.g. await MyNavigationHub.stateActions.previousPage();
Future<bool> previousPage();
Untuk menggunakan aksi state, Anda dapat melakukan hal berikut:
MyNavigationHub.stateActions.updateBadgeCount(tab: 0, count: 2);
MyNavigationHub.stateActions.resetTabIndex(0);
MyNavigationHub.stateActions.currentTabIndex(2); // Switch to tab 2
await MyNavigationHub.stateActions.nextPage(); // Journey: go to next page
Gaya Loading
Secara default, Navigation Hub akan menampilkan Widget loading default Anda (resources/widgets/loader_widget.dart) saat tab sedang loading.
Anda dapat menyesuaikan loadingStyle untuk memperbarui gaya loading.
| Gaya | Deskripsi |
|---|---|
| normal | Gaya loading default |
| skeletonizer | Gaya loading skeleton |
| none | Tanpa gaya loading |
Anda dapat mengubah gaya loading seperti ini:
@override
LoadingStyle get loadingStyle => LoadingStyle.normal();
// or
@override
LoadingStyle get loadingStyle => LoadingStyle.skeletonizer();
Jika Anda ingin memperbarui Widget loading di salah satu gaya, Anda dapat memasukkan child ke LoadingStyle.
@override
LoadingStyle get loadingStyle => LoadingStyle.normal(
child: Center(
child: Text("Loading..."),
),
);
Sekarang, saat tab sedang loading, teks "Loading..." akan ditampilkan.
Contoh di bawah ini:
class _MyNavigationHubState extends NavigationHub<MyNavigationHub> {
...
_MyNavigationHubState() : super(() async {
await sleep(3); // simulate loading for 3 seconds
return {
0: NavigationTab.tab(
title: "Home",
page: HomeTab(),
),
1: NavigationTab.tab(
title: "Settings",
page: SettingsTab(),
),
};
});
@override
LoadingStyle get loadingStyle => LoadingStyle.normal(
child: Center(
child: Text("Loading..."),
),
);
...
}
Membuat Navigation Hub
Untuk membuat Navigation Hub, Anda dapat menggunakan Metro, gunakan perintah di bawah ini.
metro make:navigation_hub base
Perintah ini akan memandu Anda melalui pengaturan interaktif di mana Anda dapat memilih tipe layout dan menentukan tab atau journey state Anda.
Ini akan membuat file base_navigation_hub.dart di direktori resources/pages/navigation_hubs/base/ Anda dengan widget anak yang terorganisir di subfolder tabs/ atau states/.