skip to Main Content

I have made a Widget (MyComplexWidget) consisting of 2 other widgets A and B.

On construction of MyComplexWidget, I pass it a callback function for one of its children widget’s (A, B) onTap/onPressed property.

The problem is that this callback requires the BuildContext of its current parent (e.g. Widget A or B) because, let’s say, internally, it does a navigation:

Navigator.pushNamed(context, "newroute");

Ideally, I would like to have this:

MyComplexWidget(
  // this cb is eventually passed on
  // Widget A's and B's constructors.
  onTap: () {
    Navigator.pushNamed(context, "newroute");
  }
);

with context being the BuildContext of the child widget (Widget A or B) which is assigned this onTap callback (inside MyComplexWidget) AND not the current BuildContext where the closure callback was created (IF ANY at all!).

BTW, Navigator.pushNamed() is just an example, there could be other things inside the callback which require the context. I am not asking for a solution on how to navigate without context etc.

How is this possible?

2

Answers


  1. Chosen as BEST ANSWER

    @Ivo's comment, in my question, provided me with a solution in which:

    1. the user-provided callback takes a context parameter, e.g. void myOnTap(BuildContext context){ ... }

    2. You do not pass directly this callback to each basic Widget's onTap property but you provide it like this: onTap: (){ myOnTap(context); } (and context is now available as we are inside a build() method).

    For example,

    // untested pseudocode
    class MyComplexWidget extends StatelessWidget {
      final void Function(BuildContext)? onTapForA;
      final void Function(BuildContext)? onTapForB;
    
      const MyComplexWidget({super.key, this.onTapForA, this.onTapForB});
    
      @override
      build(BuildContext context) {
        return Column(children: [
          InkWell( // basic widget A
            ...
            onTap: () {
              onTapForA!(context);
            },
          ),
          InkWell( // basic widget B
            ...
            onTap: () {
              onTapForB!(context);
            },
          )
        ]);
      } // build
    }
    

    Thank you for your help


  2. You can use a global key to find context of certain widget.
    However this only work in callback, the context cannot be used directly in build such as padding: MediaQuery.paddingOf(navKey.currentContext!);

    class NavWidget extends StatelessWidget {
      const NavWidget({super.key, required this.navKey});
      final GlobalKey navKey;
    
      @override
      Widget build(BuildContext context) {
        return ElevatedButton(
          onPressed: () {
            if (navKey.currentContext == null) return;
            Navigator.pushNamed(navKey.currentContext!, '/next');
          },
          child: const Text('Next'),
        );
      }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search