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 :
What I do :
In red, the persistent sidebar
and in yellow my app content
.
If I click on my profil button
in the HomeView
, the ProfilView
is displayed and my sidebar remains visible so it's ok
My 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 :
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.
SplashScreen
for exampleAny guidance on the best way to accomplish this would be appreciated.
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.