Hi I’m new to Flutter and I’m trying to add BottomNavigationBar to my application, but I got a problem as I wrote in title.
As you can see below, I’m placing a state of currentIndex and a method called when tapped in a different class.
page_frame.dart (This has a state and a method)
// ...
class PageFrame extends StatefulWidget {
const PageFrame({super.key});
@override
State<PageFrame> createState() => _PageFrameState();
}
class _PageFrameState extends State<PageFrame> {
int _currentPageIndex = 0;
final List<Widget> _pages = <Widget>[
const Home(),
const Announcement()
];
void _onPageTap(int index) {
setState(() {
_currentPageIndex = index;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor : const Color(0xFF183977),
body : _pages.elementAt(_currentPageIndex),
bottomNavigationBar : SPBottomNavigationBar(
currentIndex : _currentPageIndex,
onTap : _onPageTap
),
);
}
}
my_bottom_navigation_var.dart (This receives a state and a method from above)
// ...
class MyBottomNavigationBar extends StatefulWidget {
final int currentIndex;
final ValueChanged<int> onTap;
const MyBottomNavigationBar({required this.currentIndex, required this.onTap, Key? key})
: super(key: key);
@override
State<MyBottomNavigationBar> createState() => _MyBottomNavigationBarState();
}
class _MyBottomNavigationBarState extends State<MyBottomNavigationBar> {
late int currentIndex;
late ValueChanged<int> onTap;
@override
void initState() {
super.initState();
currentIndex = widget.currentIndex;
onTap = widget.onTap;
}
@override
Widget build(BuildContext context) {
return BottomNavigationBar(
unselectedItemColor : const Color(0xFFFFFFFF),
selectedItemColor : const Color(0xFF008BF1),
showUnselectedLabels: true,
items : const [
BottomNavigationBarItem(
icon : Icon(Icons.home),
label : 'Home',
backgroundColor : Color(0xFF000000)
),
BottomNavigationBarItem(
icon : Icon(Icons.announcement),
label : 'Announcement',
backgroundColor : Color(0xFF000000)
)
],
currentIndex : currentIndex,
onTap : onTap,
);
}
}
This results in if I tap an icon of Announcement, only the screen changes from Home to Announcement, but what icon of selected is still Home like this:
Screen : Home, Selection : Home
Screen : Announcement, Selection : Home
I thought this could happens because of lack of interactivity, even if it were, I have no idea how to get this interactive. Please tell me what to do.
Thanks.
2
Answers
Your
MyBottomNavigationBar
state class has its life-cycle, It getscurrentIndex
value for the 1st time oninitState
. You can directly access the widget class variable withYou can use like
Also you can just use stateless widget here, the parent(home) widget pass new value on index changes and this widget get rebuild automatically.
The reason your main screen is updating while the
NavigationBar
is not is simply because they have two different states.In your main screen, you have a variable with the current page index and when the user taps the
NavigationBar
you update this and redraw the widget. This will not redraw the child widget, which has its own state that hasn’t changed.There are two simple fixes for this.
NavigationBar as StatelessWidget
Since the Navbar never uses its state, you could convert it into a
StatelessWidget
and pass the active index in the constructor. That way, when the main screen changes it will rebuild theNavigationBar
with the new index.NavigationBar as StatefulWidget
The other way to fix this is to keep the
NavigationBar
as aStatefulWidget
but when the user taps you update the state in here and also pass up the selected index. Just change theonTap()
as follows:Instead of
onTap: onTap
you will writeAs you can see, you don’t even need to create a state variable for the callback function inside the
initState()
. Just call it here.