Flutter persistent sidebar
You can use a NavigatorObserver
to listen to the changes in the route.
class MyNavObserver with NavigatorObserver {
final StreamController<int> streamController;
MyNavObserver({required this.streamController});
@override
void didPop(Route route, Route? previousRoute) {
if (previousRoute != null) {
if (previousRoute.settings.name == null) {
streamController.add(3);
} else {
streamController
.add(int.parse(previousRoute.settings.name!.split('/').last));
}
}
}
@override
void didPush(Route route, Route? previousRoute) {
if (route.settings.name == null) {
streamController.add(3);
} else {
streamController.add(int.parse(route.settings.name!.split('/').last));
}
}
}
and using StreamController
you can make changes to your SidebarTemplate
by putting it inside StreamBuilder
. This will take care of all the requirements you have mentioned in the question.
Check out the live example here.
xenos92
Updated on December 30, 2022Comments
-
xenos92 over 1 year
In my application I want to have a sidebar that allows me to have access to specific functions everywhere in my application.
What I want :
- That the sidebar remains visible when I push my pages
- That I can pushNamed route or open a modal with one of the sidebar functions
- That I can not display the sidebar on certain pages
What I do :
In red, the persistent
sidebar
and in yellow myapp content
.If I click on my
profil button
in theHomeView
, theProfilView
is displayed and my sidebar remains visible so it's okMy
AppView
:class AppView extends StatelessWidget { const AppView({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return MaterialApp( title: AppConfig.kAppName, debugShowCheckedModeBanner: false, theme: AppTheme().data, builder: (context, child) => SidebarTemplate(child: child), // => I create a template onGenerateRoute: RouterClass.generate, initialRoute: RouterName.kHome, ); }
My
SidebarTemplate
: (Display the sidebar and load the page with my router)class SidebarTemplate extends StatelessWidget { final Widget? child; const SidebarTemplate({Key? key, this.child}) : super(key: key); @override Widget build(BuildContext context) { return SafeArea( child: Scaffold( body : Row( children: [ SidebarAtom(), // => My sidebar Widget Expanded( child: ClipRect( child: child! // => My view ), ) ], ) ), ); } }
My
RouterClass
:abstract class RouterClass{ static Route<dynamic> generate(RouteSettings settings){ final args = settings.arguments; switch(settings.name){ case RouterName.kHome: return MaterialPageRoute( builder: (context) => HomeView() ); case RouterName.kProfil: return MaterialPageRoute( builder: (context) => ProfilView(title: "Profil",) ); default: return MaterialPageRoute( builder: (context) => Error404View(title: "Erreur") ); } } }
How to do :
- To pushNamed or open a modal with a button from my sidebar because I have an error
The following assertion was thrown while handling a gesture: I/flutter (28519): Navigator operation requested with a context that does not include a Navigator. I/flutter (28519): The context used to push or pop routes from the Navigator must be that of a widget that is a I/flutter (28519): descendant of a Navigator widget.
- To hide the sidebar when I want like
SplashScreen
for example
Any guidance on the best way to accomplish this would be appreciated.