Flutter How to make a common widget between multiple web routes?

Viewed 305

In Short: How to make a common widget between routes that doesn't refresh on route change?


In Long: Is there any way I could create a Flutter Container which covers the entire web page except the Navigation Bar and refreshes widgets inside the container according to button clicks on Navigation Bar?

What App Layout I want:

Material App
 |
 --Navigation Bar
 |  |
 |   -- Button 1 (Current User Screen)
 |   -- Button 2 
 |   -- Button 3
 |
 -- Container (Current User Screen: Associated With Button 1)
    |
     -- A List Of Widgets Associated with Button 1
     -- A List Of Widgets Associated with Button 2
     -- A List Of Widgets Associated with Button 3
  

What I've Already Tried:

  • Create a Navigation Bar With 4 Buttons.
  • Create routes and initial route set to 1st button content.

Disadvantages Of What I've Tried:

  • I have to put NavigationBar() On Each Route.
  • Upon Changing Route, The Refresh Of NavigationRoute() takes place.

On Click Of Another Button From Navigation: It refresh's the Navigation bar too. I want bar to be common widget between routes hence route change should only affect the content change in the container of root Material App.

1 Answers

I did so (not a full code but idea):

Common widget wrapper:

class ContentPage extends StatefulWidget {
  ContentPage({required this.title, required this.body});
  final String title;
  final Widget body;
}

class _ContentPageState extends ... {
  Widget build(BuildContext context) {
    return Title(
      title: widget.title,
      color: Colors.blue,
      child: Scaffold(
        body: Row(
          children: [
            SidebarWidget(),                   // contains navigation
            const VerticalDivider(width: 1),
            ContentWidget(child: widget.body), // wrapper for all content widgets
          ],
        ),
      ),
    );
  }
}

Route handling in MaterialApp:

MaterialApp(
  ...
  onGenerateRoute: (routeSettings) {
    final uri = Uri.parse(routeSettings.name!);
    final currentPath = uri.path;
    if(currentPath == '/login') {
      return MaterialPageRoute(
        builder: (context) => LoginPage(),
        settings: RouteSettings(name: currentPath),
      );
    }
    final pageData = getPageWidgetAndTitleForTheRoute(currentPath);
    return MaterialPageRoute(
      builder: (context) {
        return ContentPage(
          title: pageData.title,
          body: pageData.builder(context),
        );
      },
      settings: RouteSettings(name: currentPath);
    );
  },
  ...
);

Routing map to be use in function getPageWidgetAndTitleForTheRoute.

final routingMap = {
  '/login': {
    'title': 'Login', 
    'widget': LoginPage(),
  },
  '/home': {
    'title': 'Home', 
    'widget': HomePage(),
  },
  ...
};
Related