Search code examples
flutterdartriverpod

Why does my PageController is not changing my PageView while using Riverpod?


I'm learning about Riverpod on flutter, I've managed to make a BottomNavBar and a PageView for Tabs, but my tab doesn't show as I click the NavBarItem it just stays there but my appbar titles and my AnimatedPositioned do update. I don't know what I'm doing wrong, please help

Here´s a video referencia explaining my trouble with PageView Video Reference

BOTTOM NAVIGATION BAR

class MenuNavBar extends ConsumerStatefulWidget {
  MenuNavBar({Key? key}) : super(key: key);

  @override
  ConsumerState<MenuNavBar> createState() => _MenuNavBarState();
}

class _MenuNavBarState extends ConsumerState<MenuNavBar>
    with TickerProviderStateMixin {
  // late TabController _tabController;
  @override
  void initState() {
    super.initState();

  }

  @override
  void dispose() {
    super.dispose();
  }

  void _onPageChanged(int index) {
    final uiProvider = ref.watch(uiProviders.notifier);
    uiProvider.setSelectedMenuOpt(index);
  }

  @override
  Widget build(BuildContext context) {
    final uiProvider = ref.watch(uiProviders);
    final currentIndex = uiProvider.selectedMenuOpt;

    return BottomNavigationBar(


        showSelectedLabels: false,
        showUnselectedLabels: false,
        items: const [
          BottomNavigationBarItem(
            icon: Image(
              image: AssetImage('assets/icons/inactive/home_tab_inactive.png'),
              width: 25,
              height: 25,
            ),
            activeIcon: Image(
              image: AssetImage('assets/icons/active/home_tab_active.png'),
              width: 30,
              height: 30,
            ),
            label: 'Inicio',
          ),
          BottomNavigationBarItem(
            icon: Image(
              image:
                  AssetImage('assets/icons/inactive/client_tab_inactive.png'),
              width: 25,
              height: 25,
            ),
            activeIcon: Image(
              image: AssetImage('assets/icons/active/client_tab_active.png'),
              width: 30,
              height: 30,
            ),
            label: 'Clientes',
          ),
          BottomNavigationBarItem(
            icon: Image(
              image: AssetImage('assets/icons/inactive/order_tab_inactive.png'),
              width: 25,
              height: 25,
            ),
            activeIcon: Image(
              image: AssetImage('assets/icons/active/order_tab_active.png'),
              width: 30,
              height: 30,
            ),
            label: 'Pedidos',
          ),
          BottomNavigationBarItem(
            icon: Image(
              image:
                  AssetImage('assets/icons/inactive/receipt_tab_inactive.png'),
              width: 25,
              height: 25,
            ),
            activeIcon: Image(
              image: AssetImage('assets/icons/active/receipt_tab_active.png'),
              width: 30,
              height: 30,
            ),
            label: 'Facturas',
          ),
        ],
        currentIndex: currentIndex,
        unselectedItemColor: Colors.grey,
        selectedItemColor: Theme.of(context).primaryColor,
        onTap: _onPageChanged);
  }
}

UI PROVIDER

class UiPrvoderState {
  int selectedMenuOpt;
  bool isEnabledSwitch;
  bool isLoadingBottomScroller;
  bool showBackToTop;
  PageController pageController;

  UiPrvoderState(
      {this.selectedMenuOpt = 0,
      this.isEnabledSwitch = false,
      this.isLoadingBottomScroller = false,
      this.showBackToTop = false,
      required this.pageController});

  UiPrvoderState copyWith({
    int? selectedMenuOpt,
    bool? isEnabledSwitch,
    bool? isLoadingBottomScroller,
    bool? showBackToTop,
    PageController? pageController,
  }) =>
      UiPrvoderState(
        selectedMenuOpt: selectedMenuOpt ?? this.selectedMenuOpt,
        isEnabledSwitch: isEnabledSwitch ?? this.isEnabledSwitch,
        isLoadingBottomScroller:
            isLoadingBottomScroller ?? this.isLoadingBottomScroller,
        showBackToTop: showBackToTop ?? this.showBackToTop,
        pageController: pageController ?? this.pageController,
      );
}

class UiProviderNotifier extends StateNotifier<UiPrvoderState> {
  UiProviderNotifier()
      : super(UiPrvoderState(pageController: PageController()));

  void setSelectedMenuOpt(int i, {PageController? pageController}) {
    state = state.copyWith(selectedMenuOpt: i);
    pageController?.animateToPage(i,
        duration: const Duration(milliseconds: 300), curve: Curves.easeInOut);
  }

  void setIsEnabledSwitch(bool value) {
    state = state.copyWith(isEnabledSwitch: value);
  }

  void setIsLoadingBottomScroller(bool value) {
    state = state.copyWith(isLoadingBottomScroller: value);
  }

  void setShowBackToTop(bool value) {
    state = state.copyWith(showBackToTop: value);
  }
}

final uiProviders =
    StateNotifierProvider.autoDispose<UiProviderNotifier, UiPrvoderState>(
        (ref) {
  return UiProviderNotifier();
});

PAGE VIEW

class _MainMenuTabs extends ConsumerStatefulWidget {
  _MainMenuTabs({Key? key}) : super(key: key);

  @override
  ConsumerState<_MainMenuTabs> createState() => __MainMenuTabsState();
}

class __MainMenuTabsState extends ConsumerState<_MainMenuTabs> {
  @override
  Widget build(BuildContext context) {

    final uiProvider = ref.watch(uiProviders);
    return Container(
        height: MediaQuery.of(context).size.height,
        margin: EdgeInsets.only(left: 5, right: 5, top: 0, bottom: 20),
        padding: EdgeInsets.only(top: 0, bottom: 50),
        child: PageView(
            scrollBehavior: const ScrollBehavior(),
            controller: uiProvider.pageController,
            children: <Widget>[
              MainTab(
                dayOfMonth: DateTime.now().day,
                date: '${DateTime.now()}',
                totalAppointments: 40,
                appointmentsLeft: 40 - 1,
              ),
              ClientTab(),
              OrderTab(),
              Container(
                color: Colors.yellow,
              ),
            ]));
  }
}


Solution

  • You didn't pass the pageController to uiProvider.setSelectedMenuOpt(index);

    You need to use state.pageController in setSelectedMenuOpt.

    Code:

    void setSelectedMenuOpt(int i) {
        state = state.copyWith(selectedMenuOpt: i);
        state.pageController?.animateToPage(i,
            duration: const Duration(milliseconds: 300), curve: Curves.easeInOut);
      }