skip to Main Content

I have a flutter application with a bottom navigation bar that keeps page states in the navigation (I use go_router). I’ve been trying for a long time to get a callback on my fav page as soon as I arrive on the page. But I can’t, so here’s an outline of what I’d like:

Page 1 (which manages navigation):

void _tabChanged() {
   ...
}
...
LazyIndexedStack(
              index: _controller.index,
              children: const [
                Home(),
                Fav(), // it should be sent the callback, linked with tabChanged()
              ],
            ),

And for the page, you’d have to receive the callback:

const Fav({Key? key, required this.callback}) : super(key: key);
...
widget.callback() {
... here I receive the callback from tab.dart
}

2

Answers


  1. Chosen as BEST ANSWER

    Thank you very much PurplePolyhedron, I received an error so here's how I did it in the end:

    GlobalKey<FavState> key = GlobalKey<FavState>();
    void _handleTabChanged() {
      if (_tabController.index == 1) {
        WidgetsBinding.instance.addPostFrameCallback((_) {
          if (key.currentState != null) {
            key.currentState!.test();
          }
        });
      }
      ...
    }
    ...
    LazyIndexedStack(
      index: _controller.index,
        children: [
          const Home(),
          Fav(
            key: key,
          ),
        ],
    ),
    

    and in the Fav page:

    void test() {
        setState(() {
          ...
        });
      }
    

  2. I assume you want the navigation bar to call some method of the State<Fav>. You can find the state using a GlobleKey

    import 'package:flutter/material.dart';
    
    class MyPage extends StatelessWidget {
      const MyPage({super.key});
    
      @override
      Widget build(BuildContext context) {
        final key = GlobalKey();
        return Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            MyWidget(key: key),
            ElevatedButton(
                onPressed: () {
                  (key.currentState as _MyWidgetState).change();
                },
                child: const Text("Change"))
          ],
        );
      }
    }
    
    class MyWidget extends StatefulWidget {
      const MyWidget({super.key});
    
      @override
      State<MyWidget> createState() => _MyWidgetState();
    }
    
    class _MyWidgetState extends State<MyWidget> {
      int counter = 0;
      void change() {
        setState(() {
          counter++;
        });
      }
    
      @override
      Widget build(BuildContext context) {
        return Text("Counter: $counter");
      }
    }
    

    Or you can pass a Listenable, subscribe to it in Fav, and trigger the callback in navigation bar.

    import 'package:flutter/material.dart';
    
    class MyPage extends StatefulWidget {
      const MyPage({super.key});
    
      @override
      State<MyPage> createState() => _MyPageState();
    }
    
    class _MyPageState extends State<MyPage> {
      late ChangeNotifier notifier;
    
      @override
      void initState() {
        super.initState();
        notifier = ChangeNotifier();
      }
    
      @override
      void dispose() {
        notifier.dispose();
        super.dispose();
      }
    
      @override
      Widget build(BuildContext context) {
        return Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            MyWidget(notifier: notifier),
            ElevatedButton(onPressed: notifier.notifyListeners, child: const Text("Change"))
          ],
        );
      }
    }
    
    class MyWidget extends StatefulWidget {
      final ChangeNotifier notifier;
      const MyWidget({super.key, required this.notifier});
    
      @override
      State<MyWidget> createState() => _MyWidgetState();
    }
    
    class _MyWidgetState extends State<MyWidget> {
      int counter = 0;
      void change() {
        setState(() {
          counter++;
        });
      }
    
      @override
      void initState() {
        super.initState();
        widget.notifier.addListener(change);
      }
    
      @override
      void dispose() {
        widget.notifier.removeListener(change);
        super.dispose();
      }
    
      @override
      Widget build(BuildContext context) {
        return Text("Counter: $counter");
      }
    }
    

    However, the best practice is to separate the logic from the widget tree instead of doing everything in State

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search