Using Provider with with TickerProviderStateMixin: Where can I initialise my controller?

Viewed 4484

I am just playing around with Flutter and I have run into a bit of an issue -> here is my repo: https://github.com/LuckyRon88/FlutterWebCV

I am using https://pub.dev/packages/motion_tab_bar/example to create a bottom Navigation bar as a Children of a stack. I will use this Bottom Navigation bar on multiple pages to change a widget on the screen so I refactored my code to have a BottomNavigation.dart.

I am using provider as my State management solution.

This is the TabBar https://github.com/LuckyRon88/FlutterWebCV/blob/master/lib/Components/TestTab.dart

which I want to use on https://github.com/LuckyRon88/FlutterWebCV/blob/master/lib/Screens/Education.dart but I need to be able to access the eduTabController (from TestTab.dart) from Education.dart to change some info on this very same page.

I already have a provider model https://github.com/LuckyRon88/FlutterWebCV/blob/master/lib/ProviderPack/PageController.dart but I am unsure how to give Provider the control of my eduTabController since I cannot initialise it anywhere but on the TestTab.dart itself.

1 Answers

Since the controller in required in MotionTabView and not in MotionTabBar move the _eduTabController to Education class. Now define the function that is required on tab selection ,i.e, onTabItemSelected in Education class and pass it as an argument to TestTab.

This way you can avoid having the _eduTabController in TestTab and use it in MotionTabView which exist in Education.

Here is a rough implementation:

// convert Education to StatefulWidget
class Education extends StatefulWidget {

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

// Requires SingleTickerProviderStateMixin
class _EducationState extends State<Education> with SingleTickerProviderStateMixin {
  final MotionTabController _eduTabController; // have your controller here

  @override
  void initState() {
    super.initState();
    // initialize controller
    _eduTabController = MotionTabController(initialIndex: 1, vsync: this);
  }

  @override
  void dispose() {
    super.dispose();
    // dispose controller
    _eduTabController?.dispose();
  }

  // Extract your function from TestTab
  void onTabItemSelected(int value) {
    setState(() {
      _eduTabController.index = value;
    });
  },
  
  @override
  Widget build(BuildContext context) {
    //...

         Align(
           alignment: Alignment.bottomCenter,
           child: TestTab(
             // don't pass the controller
             onTabItemSelected: onTabItemSelected, // pass the function instead
           ), 
         ),

         MotionTabBarView(
           controller: _eduTabController,
           // ...
         ),

    //...
  }

}
// This should be a StatelessWidget (because it has no state)
// Change to StatefulWidget if your requirements change
class TestTab extends StatefulWidget {
  final Function onTabItemSelected;

  TestTab({this.onTabItemSelected}); // receive your function here

  @override
  Widget build(BuildContext context) {
    return MotionTabBar(
      // ...

      onTabItemSelected: onTabItemSelected, // use the function here

      // ...
    );
  }
}
Related