Flutter persistent sidebar

209

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.

Share:
209
xenos92
Author by

xenos92

Updated on December 30, 2022

Comments

  • xenos92
    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 :

    enter image description here

    In red, the persistent sidebar and in yellow my app content.

    enter image description here

    If I click on my profil button in the HomeView, the ProfilView is displayed and my sidebar remains visible so it's ok

    enter image description here

    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 :

    • 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.