I am new to flutter and I did find similar questions on SO but am too novice to understand the nuance so apologies if this question is too similar to an already asked one.
I have a BottomNavigationBar
which has 3 icons (Home, Play and Create) which should navigate between these 3 routes/pages.
main.dart
routes: {
"/home": (context) => MyHomePage(title: "STFU"),
"/play": (context) => Play(),
"/create": (context) => Create(),
"/settings": (context) => Settings(),
},
I extracted my navbar into a custom class so my 3 separate pages could use it:
bottom-nav.dart
class MyBottomNavBar extends StatefulWidget {
MyBottomNavBar({
Key? key,
}) : super(key: key);
@override
State<MyBottomNavBar> createState() => _MyBottomNavBarState();
}
class _MyBottomNavBarState extends State<MyBottomNavBar> {
int _selectedIndex = 0;
void _onTapped(int index) => {
print("_onTapped called with index = $index"),
setState(
() => _selectedIndex = index,
)
};
@override
Widget build(BuildContext context) {
return BottomNavigationBar(
backgroundColor: Colors.orangeAccent[100],
currentIndex: _selectedIndex,
onTap: (value) => {
print("value is $value"),
// find index and push that
_onTapped(value),
if (value == 0)
{Navigator.pushNamed(context, "/home")}
else if (value == 1)
{Navigator.pushNamed(context, "/play")}
else if (value == 2)
{Navigator.pushNamed(context, "/create")}
},
items: [
BottomNavigationBarItem(label: "Home", icon: Icon(Icons.home_filled)),
BottomNavigationBarItem(
label: "Play", icon: Icon(Icons.play_arrow_rounded)),
BottomNavigationBarItem(label: "Create", icon: Icon(Icons.create)),
],
);
}
}
so now i just set this MyBottomNavBar
class to the bottomNavigationBar
property of the Scaffold widget my inside Home page, Play page and Create page for eg.
home.dart
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Home"),
),
body: Column(
children: [
Container(
padding: EdgeInsets.all(20.00),
child: Text("inside home"),
),
],
),
bottomNavigationBar: MyBottomNavBar(),
);
}
}
play.dart
class Play extends StatefulWidget {
const Play({super.key});
@override
State<Play> createState() => _PlayState();
}
class _PlayState extends State<Play> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Container(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text("inside play page"),
SizedBox(
height: 30.00,
),
Text("some text"),
],
),
),
bottomNavigationBar: MyBottomNavBar(),
);
}
}
The nav bar buttons work to switch between pages but for some reason the currentIndex
value isn't getting updated and stays at 0 (i.e on the "Home" icon). When I debug it I can see _selectedIndex
getting updated inside inside the _onTapped
function which should update the currentIndex value but it doesn't appear to do so. Any help would be appreciated
What you have here is three different pages with their separate BottomNavBar class instance. Instead you should have a shared Scaffold and one bottomNavBar so that when you navigate bottomNavbar state does not reset.
You can use PageView to do this.
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key});
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
@override
void initState() {
super.initState();
}
List<Widget> pages = const [Home(), Play(), Create()];
final _pageController = PageController();
int _selectedIndex = 0;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
bottomNavigationBar: BottomNavigationBar(
currentIndex: _selectedIndex,
onTap: (index) {
_pageController.jumpToPage(index);
_selectedIndex = index;
setState(() {});
},
items: const [
BottomNavigationBarItem(icon: Icon(Icons.home), label: 'Home'),
BottomNavigationBarItem(icon: Icon(Icons.play_arrow), label: 'Play'),
BottomNavigationBarItem(icon: Icon(Icons.create), label: 'Create'),
],
backgroundColor: Colors.greenAccent,
),
body: PageView(
controller: _pageController,
children: pages,
),
);
}
}
class Home extends StatelessWidget {
const Home({super.key});
@override
Widget build(BuildContext context) {
return const Placeholder();
}
}
class Play extends StatelessWidget {
const Play({super.key});
@override
Widget build(BuildContext context) {
return const Placeholder();
}
}
class Create extends StatelessWidget {
const Create({super.key});
@override
Widget build(BuildContext context) {
return const Placeholder();
}
}