Navigating for the part of a screen in flutter

Viewed 355

Goal

I want to push pages on the sibling widgets from any sibling widgets, I have achieved it using Global keys of Navigator state but it gives the error indicating that "Duplicate GlobalKey detected in widget tree."

I have attached screenshots below for understanding, what alternative way should I follow instead of Global key?

Below is the code what I have tried

Main file

import 'package:get/get.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key key}) : super(key: key);

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Right Slider Navigation Demo',
      theme: ThemeData(
        primarySwatch: Colors.blueGrey,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: PageOne(),
    );
  }
}

RightSideNavigator class

class RightSideNavigator extends StatelessWidget {
  final String initialRoute;
  final Map<String, WidgetBuilder> routes;

  RightSideNavigator({
    Key key,
    @required this.initialRoute,
    @required this.routes,
  }) : super(key: key);

  static GlobalKey<NavigatorState> navigationKey = GlobalKey();

  static NavigatorState navigator() {
    NavigatorState state;
    if (navigationKey.currentState != null) {
      state = navigationKey.currentState;
    }
    return state;
  }

  @override
  Widget build(BuildContext context) {
    return WillPopScope(
      child: Navigator(
        key: navigationKey,
        initialRoute: initialRoute,
        onGenerateRoute: (routeSettings) {
          return PageRouteBuilder(
            pageBuilder: (context, __, ___) =>
                routes[routeSettings.name](context),
            settings: routeSettings,
            transitionsBuilder:
                (context, animation, secondaryAnimation, child) {
              final tween = Tween(begin: Offset(1, 0), end: Offset(0, 0))
                  .animate(animation);
              return SlideTransition(
                position: tween,
                child: child,
              );
            },
          );
        },
      ),
      onWillPop: () {
        if(navigationKey.currentState.canPop()) {
          navigationKey.currentState.pop();
          return Future<bool>.value(false);
        }
        return Future<bool>.value(true);
      },
    );
  }
}

PageOne

class PageOne extends StatefulWidget {
  const PageOne({Key key}) : super(key: key);

  @override
  State<PageOne> createState() => _PageOneState();
}

class _PageOneState extends State<PageOne> {

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text("Page One"),),
      body: Row(
        children: [
          Expanded(
            child: Center(
              child: Column(
                mainAxisSize: MainAxisSize.min,
                children: [
                  ElevatedButton(
                    onPressed: (){
                      Navigator.of(context).push(MaterialPageRoute(builder: (context) => PageTwo()));
                    },
                    child: Text("Go to Page Two"),
                  ),
                  SizedBox(height:20),
                  ElevatedButton(
                    onPressed: (){
                      RightSideNavigator.navigator().push(MaterialPageRoute(builder: (context) => MenuOne()));
                    },
                    child: Text("Open Menu One"),
                  ),
                ],
              ),
            ),

          ),
          Container(
            decoration: BoxDecoration(border: Border.all(color: Colors.blueGrey)),
            child: ConstrainedBox(
              constraints: BoxConstraints.tightFor(width: MediaQuery.of(context).size.width * 0.3),
              child: RightSideNavigator(
                initialRoute: "/",
                routes: {
                  '/': (context) => RightSideNavigationView(),
                  '/menu_one': (context) => MenuOne(),
                },
              ),
            ),
          )
        ],
      ),
    );
  }
}

RightSideNavigationView

class RightSideNavigationView extends StatelessWidget {
  const RightSideNavigationView({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Column(
          children: [
            ElevatedButton(
              onPressed: (){
                RightSideNavigator.navigator().pushNamed("/menu_one");
              },
              child: Text("Menu One"),
            )
          ],
        ),
      ),
    );
  }
}

MenuOne class

class MenuOne extends StatelessWidget {
  const MenuOne({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text("Menu One"),),
      body: Center(child: Column(
        children: [
          ElevatedButton(child: Text("Back"),onPressed: () => RightSideNavigator.navigator().pop(),),

        ],
      )),
    );
  }
}

PageTwo class

class PageTwo extends StatefulWidget {
  const PageTwo({Key key}) : super(key: key);

  @override
  _PageTwoState createState() => _PageTwoState();
}

class _PageTwoState extends State<PageTwo> {


  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text("Page Two"),),
      body: Row(
        children: [
          Expanded(
            child: Center(
              child: Column(
                mainAxisSize: MainAxisSize.min,
                children: [
                  ElevatedButton(
                    onPressed: (){
                      Navigator.of(context).pop();
                    },
                    child: Text("Back"),
                  ),
                  SizedBox(height:20),
                  ElevatedButton(
                    onPressed: (){
                      RightSideNavigator.navigator().push(MaterialPageRoute(builder: (context) => MenuOne()));
                    },
                    child: Text("Open Menu One"),
                  ),
                ],
              ),
            ),
          ),
          Container(
            decoration: BoxDecoration(border: Border.all(color: Colors.blueGrey)),
            child: ConstrainedBox(
              constraints: BoxConstraints.tightFor(width: MediaQuery.of(context).size.width * 0.3),
              child: RightSideNavigator(
                initialRoute: "/",
                routes: {
                  '/': (context) => RightSideNavigationView(),
                  '/menu_one': (context) => MenuOne(),
                },
              ),
            ),
          )
        ],
      ),
    );
  }
}

Page One

This is Page One, on click of Open Menu One button it opens the MenuOne page as expected

Open MenuOne page on click of Open Menu Button

Menu One page opens as expected

Page Two

Problem

When I navigate to Page Two and click on open menu button, it opens but gives the error

======== Exception caught by widgets library =======================================================
The following assertion was thrown while finalizing the widget tree:
Duplicate GlobalKey detected in widget tree.

The following GlobalKey was specified multiple times in the widget tree. This will lead to parts of the widget tree being truncated unexpectedly, because the second time a key is seen, the previous instance is moved to the new location. The key was:
- [LabeledGlobalKey<NavigatorState>#55dab]
This was determined by noticing that after the widget with the above global key was moved out of its previous parent, that previous parent never updated during this frame, meaning that it either did not update at all or updated before the widget was moved, in either case implying that it still thinks that it should have a child with that global key.
The specific parent that did not update after having one or more children forcibly removed due to GlobalKey reparenting is:
- WillPopScope(dependencies: [_ModalScopeStatus], state: _WillPopScopeState#cf014)
A GlobalKey can only be specified on one widget at a time in the widget tree.
When the exception was thrown, this was the stack: 
#0      BuildOwner.finalizeTree.<anonymous closure> (package:flutter/src/widgets/framework.dart:2939:15)
#1      BuildOwner.finalizeTree (package:flutter/src/widgets/framework.dart:2964:8)
#2      WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:880:19)
#3      RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:328:5)
#4      SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1143:15)
#5      SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:1080:9)
#6      SchedulerBinding._handleDrawFrame (package:flutter/src/scheduler/binding.dart:996:5)
#10     _invoke (dart:ui/hooks.dart:163:10)
#11     PlatformDispatcher._drawFrame (dart:ui/platform_dispatcher.dart:259:5)
#12     _drawFrame (dart:ui/hooks.dart:126:31)
(elided 3 frames from dart:async)
====================================================================================================
0 Answers
Related