Search code examples
flutterflutter-providerflutter-pageview

Flutter - Trigger PageView change on Provider value change


I have a custom BottomAppBar with PageView for pages. I am trying to change the pages as the user clicks on items in the BottomAppBar. I am using Provider to manage Global State. Clicking on items triggers the value change in the provider but there is no method in PageView to trigger page change on a value change. How can I achieve this? Below is my code.

My Provider:

class CurrentPage extends ChangeNotifier {
  int _currentPage = 0;
  int get currentPage => _currentPage;

  setCurrentPage(int val) {
    _currentPage = val;
    notifyListeners();
  }
}

A BottomAppBar Item:

 InkWell(
                onTap: () {
                  context.read<CurrentPage>().setCurrentPage(0);
                },
                child: Padding(
                  padding: const EdgeInsets.symmetric(
                      horizontal: 26.5, vertical: 17.0),
                  child: Column(
                    mainAxisSize: MainAxisSize.min,
                    children: <Widget>[
                      Icon(
                        CustomIcons.home,
                        size: 18.0,
                        color: context.watch<CurrentPage>().currentPage == 0
                            ? Color(0xFF2C1DEB)
                            : Color(0xFFCCCCD5),
                      ),
                      SizedBox(height: 9.0),
                      Text(
                        'HOME',
                        style: TextStyle(
                          color: context.watch<CurrentPage>().currentPage == 0
                              ? Color(0xFF2C1DEB)
                              : Color(0xFFCCCCD5),
                          fontWeight: FontWeight.w800,
                          fontSize: 10.0,
                          letterSpacing: 1.0,
                        ),
                      ),
                    ],
                  ),
                ),
              ),

PageView:

class Pages extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final PageController _pageController =
        PageController(initialPage: context.watch<CurrentPage>().currentPage);

    return PageView(
      onPageChanged: (int) {},
      controller: _pageController,
      scrollDirection: Axis.horizontal,
      pageSnapping: true,
      children: [
        Container(
          color: Colors.green,
          child: Text('Home Page'),
        ),
        Container(
          child: Text('Profile Page'),
        ),
        Container(
          child: Text('Search Page'),
        ),
        Container(
          child: Text('Jobs Page'),
        ),
      ],
    );
  }
}

Solution

  • This is how you can make it. Once you call notifyListener from your provider, if the currentPage has changed, this will go to the new selected page

    class Pages extends StatelessWidget {
          final PageController _pageController =
                PageController(initialPage:0);
          @override
          Widget build(BuildContext context) {
    
    
        return Consumer<CurrentPage>(builder:(ctx, currentPage,  widget){
    
         final pageView = PageView(
              onPageChanged: (int) {},
              controller: _pageController,
              scrollDirection: Axis.horizontal,
              pageSnapping: true,
              children: [
                Container(
                  color: Colors.green,
                  child: Text('Home Page'),
                ),
                Container(
                  child: Text('Profile Page'),
                ),
                Container(
                  child: Text('Search Page'),
                ),
                Container(
                  child: Text('Jobs Page'),
                ),
              ],);
              if(currentPage.currentPage != _pageController.page.floor()){
                _pageController.jumpToPage(currentPage.currentPage);
              }
              return pageView;
              }
            );
          }
        }