Flutter - Trigger PageView change on Provider value change

Viewed 4026

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'),
        ),
      ],
    );
  }
}
2 Answers

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;
          }
        );
      }
    }

You should use animateToPage or jumpToPage methods in PageViewController. also you need to make your Page widget StatefullWidget.

Related