Created
April 22, 2021 03:00
-
-
Save darkfrog26/d39004a8b271764f2a4bacfe4ff2f3bc to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'package:flutter/material.dart'; | |
import 'package:get/get.dart'; | |
class Screen { | |
final String key; | |
final Nav? nav; | |
final Widget Function() createWidget; | |
Screen({ | |
required this.key, | |
this.nav, | |
required this.createWidget | |
}); | |
String url() => '/$key'; | |
} | |
class Nav { | |
final String label; | |
final IconData icon; | |
Nav(this.label, this.icon); | |
} | |
class Application extends StatelessWidget { | |
final String title; | |
final ThemeData theme; | |
final List<Screen> screens; | |
final List<Screen> navScreens; | |
final Map<String, Screen> urlMap; | |
final String initialURL; | |
late NavService navService; | |
Application({ | |
required this.title, | |
required this.theme, | |
required this.screens | |
}) : | |
navScreens = screens.where((s) => s.nav != null).toList(), | |
urlMap = Map.fromIterable(screens, key: (s) => '/${s.key}', value: (s) => s), | |
initialURL = screens[0].url(); | |
push(Screen screen) => navService.goToScreen(screen); | |
Widget build(BuildContext context) { | |
navService = NavService(this); | |
return GetMaterialApp( | |
title: title, | |
theme: theme, | |
initialBinding: BindingsBuilder.put(() => navService), | |
home: Home(initialURL: initialURL), | |
); | |
} | |
} | |
class NavService extends GetxService { | |
final Application app; | |
final activeIndex = 0.obs; | |
NavService(this.app); | |
@override | |
void onInit() { | |
ever(activeIndex, (int index) { | |
print('ActiveIndex changed: $activeIndex'); | |
var url = app.navScreens[index].url(); | |
Get.toNamed(url, id: 1); | |
}); | |
super.onInit(); | |
} | |
@override | |
void onClose() { | |
super.onClose(); | |
} | |
void processRouting(Routing? route) { | |
print('ProcessRouting: ${route?.route?.settings.name}'); | |
String url = route!.route!.settings.name!; | |
Screen? screen = app.urlMap[url]; | |
if (screen != null) { | |
int index = app.navScreens.indexOf(screen); | |
if (index >= 0) { | |
activeIndex(index); | |
} else { | |
Get.to(screen.createWidget); | |
} | |
} | |
} | |
void goToScreen(Screen screen) => Get.toNamed(screen.url()); | |
GetPageRoute onGenerateRoute(RouteSettings settings) { | |
final currentUrl = settings.name; | |
final screen = app.urlMap[currentUrl]; | |
final GetPageBuilder page = () { | |
if (screen != null) { | |
return screen.createWidget(); | |
} else { | |
return Center(child: Text('Error! No route for $currentUrl (${app.urlMap.keys})')); | |
} | |
}; | |
return GetPageRoute( | |
routeName: currentUrl, | |
settings: settings, | |
page: page | |
); | |
} | |
} | |
class AppNavigatorObserver extends NavigatorObserver { | |
static int stack = 0; | |
@override | |
void didPush(Route<dynamic> route, Route<dynamic>? previousRoute) { | |
super.didPush(route, previousRoute); | |
if (route.settings.name != '/') { | |
stack++; | |
} | |
} | |
} | |
class Home extends GetWidget<NavService> { | |
final String _initialURL; | |
const Home({Key? key, required String initialURL}): | |
_initialURL = initialURL, | |
super(key: key); | |
@override | |
Widget build(BuildContext context) { | |
return WillPopScope( | |
child: Scaffold( | |
body: Navigator( | |
key: Get.nestedKey(1), | |
initialRoute: _initialURL, | |
observers: [ | |
GetObserver(controller.processRouting, Get.routing), | |
AppNavigatorObserver() | |
], | |
onGenerateRoute: controller.onGenerateRoute, | |
), | |
bottomNavigationBar: Obx( | |
() => BottomNavigationBar( | |
currentIndex: controller.activeIndex(), | |
onTap: controller.activeIndex, | |
items: controller.app.navScreens | |
.map((s) => BottomNavigationBarItem( | |
icon: Icon(s.nav!.icon), | |
label: s.nav!.label | |
) | |
).toList(), | |
), | |
), | |
), | |
onWillPop: onWillPop | |
); | |
} | |
Future<bool> onWillPop() async { | |
AppNavigatorObserver.stack--; | |
if (AppNavigatorObserver.stack <= 0) { | |
AppNavigatorObserver.stack = 0; | |
return true; | |
} else { | |
Get.back(id: 1); | |
return false; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment