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,
),
]));
}
}
2
Answers
You didn’t pass the paegController to uiProvider.setSelectedMenuOpt(index);
You need to use state.pageController in setSelectedMenuOpt.
Code:
The most likely issue is that your
UiPrvoderState
is not immutable. Recall that an immutable object must have allfinal
fields, and const is used when creating an instance.Also stop using
StateNotifier
. This provider is recognized as obsolete and may soon disappear in the new version of riverpod. UseNotifier
instead.