Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Persisting AppBar Drawer across all Pages Flutter

Tags:

flutter

dart

I am trying to create a uniform drawer that is accessible across all pages in my app. How do I make it persist throughout all these pages without having to recreate my custom Drawer widget in every single dart file?

like image 619
HDiamond Avatar asked Aug 02 '18 18:08

HDiamond


People also ask

How do you show the drawers in all pages in Flutter?

To share a drawer between all pages we could add a builder in our MaterialApp instance. This will instantiate a Scaffold under Navigator but above all routes. Inside your page, you can instantiate another Scaffold without restriction as you'd usually do.

How do you open the drawer from another widget in Flutter?

The navigation drawer in Flutter allows users to navigate to different pages of your app. The navigation drawer is added using the Drawer widget. It can be opened via swipe gesture or by clicking on the menu icon in the app bar.

How can I have my AppBar in a separate file in Flutter?

if you want to make a custom appbar in a different file so that it can be shared you can just make your new app bar extend it and then pass your customization to super(), in your case your KainAppBar will extend the GradientAppBar like below how MyAppBar extends AppBar.


2 Answers

There are a few different options for this. The most basic is hopefully something you've already done, but I'll list it anyways:

1: Create a class for your drawer

Your widget should be its own stateful or stateless widget. This way, you just have to instantiate it each time.

class MyDrawer extends StatelessWidget {   @override   Widget build(BuildContext context) {     return Drawer(...);   } } 

And then when using it in each page:

Scaffold(   drawer: MyDrawer(...),   ... ) 

I hope you're already doing this; if not you should be. A class's build function shouldn't be too large or it can lead to poor performance and harder to maintain code; splitting things into logical units will help you in the long run.

2: Create a class for your scaffold

If having to include the same drawer in a scaffold for each page is still too much code, you can instead use a class that encapsulates your scaffold. It would essentially take inputs for each of the scaffold inputs you actually use.

class MyScaffold extends StatelessWidget {    final Widget body;    MyScaffold({this.body});    @override   Widget build(BuildContext context) {     return Scaffold(      body: body,      drawer: MyDrawer(...),     );   } } 

And then instead of using Scaffold in your code, use MyScaffold (but please name it something better =D).

3: Multi level scaffold

I'm only including this way of doing it to be complete, and I don't recommend it. That being said, there are certain things you can't get to work within flutter's normal workflow that you could do by doing this - for example if you want a custom animation for when the user taps on different items in the drawer.

Basically, what you'd do in this case is to have a Scaffold outside of your MaterialApp or Navigator (which I believe would also mean you'd have to have another Navigator outside that, but I'm not 100% sure). You would have the scaffold that's outside your navigation show the drawer while the other one (on each page within the navigation) would do whatever else you need it to do. There's a few caveats - you'd have to make sure you get the right scaffold (i.e. Scaffold.of(context) by itself wouldn't cut it - you'd have to get the context of the first scaffold and use it to find the higher-level one), and you'd probably need to pass a GlobalKey (of the lower-level scaffold) to the Drawer so that it could actually change pages within it.

As I said, I don't recommend this approach, so I'm not going to go into any more detail than that but rather leave it as an exercise for the reader if they want to go down that rabbit hole!

like image 60
rmtmckenzie Avatar answered Sep 24 '22 04:09

rmtmckenzie


rmtmckenzie is very correct.

Although if you are curious about the multi scaffold solution, this can be more elegant than you think.

To share a drawer between all pages we could add a builder in our MaterialApp instance. This will instantiate a Scaffold under Navigator but above all routes.

MaterialApp(   title: 'Flutter Demo',   builder: (context, child) {     return Scaffold(       drawer: MyDrawer(),       body: child,     );   },   home: MyHome() ) 

Inside your page, you can instantiate another Scaffold without restriction as you'd usually do.

You can then show the shared drawer by doing the following in any widget under MaterialApp :

final ScaffoldState scaffoldState = context.rootAncestorStateOfType(TypeMatcher<ScaffoldState>()); scaffoldState.openDrawer(); 

Code which you can extract into a nice helper :

class RootScaffold {   static openDrawer(BuildContext context) {     final ScaffoldState scaffoldState =         context.rootAncestorStateOfType(TypeMatcher<ScaffoldState>());     scaffoldState.openDrawer();   } } 

Then reuse using RootScaffold.openDrawer(context)

like image 24
Rémi Rousselet Avatar answered Sep 23 '22 04:09

Rémi Rousselet