Flutter BottomNavigationBar in all pages - flutter

I want to make this: https://medium.com/coding-with-flutter/flutter-case-study-multiple-navigators-with-bottomnavigationbar-90eb6caa6dbf. I'm working with Getx. First I have a screen called NavigatorPage, the controller is NavigatorController(). The problem is that in my HomePage() I use Get.toNamed('otheRoute') and I lose the Appbar and the BottomNavigationBar. I nedd to achieve the result as the link.
This is my navigator page
class NavigatorPage extends GetWidget<NavigatorController> {
NavigatorPage({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
extendBodyBehindAppBar: true,
appBar: CustomAppBar(),
body: Obx(() => IndexedStack(
index: controller.tabIndex.value,
children: [
HomePage(),
//SecondPage(),
],
)),
bottomNavigationBar: Obx(() => BottomNavigationBar(
onTap: controller.changePage,
currentIndex: controller.tabIndex.value,
items: [
BottomNavigationBarItem(
icon: Icon(Icons.home),
label: 'home',
),
BottomNavigationBarItem(
icon: Icon(Icons.download),
label: 'download',
),
])),
);
}
}
This is my navigator controller
class NavigatorController extends GetxController {
var tabIndex = 0.obs;
changePage(int index) {
tabIndex(index);
print('Index: $tabIndex');
}
}

Related

Hide bottomnavigation in specific pages in flutter?

I created a separate file for bottom navigation bar and included the three screens which is to be included in bottom navigation bar .
class _bottomnavscreen extends State<bottomnavscreen> {
int _selectedIndex = 0;
List<Widget> pageList = [home(), create(), profile()];
void _onItemTapped(int index) {
setState(() {
_selectedIndex = index;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
bottomNavigationBar: BottomNavigationBar(
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(Icons.home),
label: 'Home',
),
BottomNavigationBarItem(
icon: Icon(Icons.add_circle_outline_sharp),
label: 'Create',
),
BottomNavigationBarItem(
icon: Icon(Icons.person),
label: 'Profile',
),
],
currentIndex: _selectedIndex,
selectedItemColor: Colors.amber[800],
onTap: _onItemTapped,
),
body: pageList.elementAt(_selectedIndex),
);
}
I put this bottomnavscreen as the home in main.dart:
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: bottomnavscreen(),
);
}
}
But this bootomnavigation widget is seen in my detailedpost screen and comment screen.
detailedpost screen is pushed from home() through Navigation.push()
Comment screen is pushed from postdetails() through
Navigation.push()
How can I hide this bottom navigation widget in my comment screen and detailedpost screen?
This is how I push to detailpost screen from home()
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => detailpost(
body: document['body'],
title: document['title'],
date: document['date'],
)),
);
You can add condition for specific index like this :
class _bottomnavscreen extends State<bottomnavscreen> {
int _selectedIndex = 0;
List<Widget> pageList = [home(), create(), profile()];
void _onItemTapped(int index) {
setState(() {
_selectedIndex = index;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
bottomNavigationBar: _selectedIndex == 1 ? Container() : BottomNavigationBar(
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(Icons.home),
label: 'Home',
),
BottomNavigationBarItem(
icon: Icon(Icons.add_circle_outline_sharp),
label: 'Create',
),
BottomNavigationBarItem(
icon: Icon(Icons.person),
label: 'Profile',
),
],
currentIndex: _selectedIndex,
selectedItemColor: Colors.amber[800],
onTap: _onItemTapped,
),
body: pageList.elementAt(_selectedIndex),
);
}
You should start a base page from the MyApp and add BottomNavigations in that page only.
Now when you navigate to detailedpost screen and comment screen, the BottomNavigations will not be visible.
you can use the offstage property to hide the bottom navigation bar on specific pages by wrapping it in an Offstage widget and setting the offstage property to true:
import 'package:flutter/material.dart';
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _currentIndex = 0;
final List<Widget> _pages = [ HomePage(), SettingsPage(), ];
#override
Widget build(BuildContext context) {
return Scaffold(
body: _pages[_currentIndex],
bottomNavigationBar: Offstage(
offstage: _currentIndex == 1,
child: BottomNavigationBar(
currentIndex: _currentIndex,
onTap: (index) {
setState(() {
_currentIndex = index;
});
},
items: [
BottomNavigationBarItem(
icon: Icon(Icons.home),
title: Text('Home'),
),
BottomNavigationBarItem(
icon: Icon(Icons.settings),
title: Text('Settings'),
),
],
),
),
);
}
}

How to set index of TabBarView?

I'm trying to mount BottomNavigationBar to TabBarView. How to set the index of TabBarView so I can display 2nd item (search page)? should I use Ontap and switch case? still how to set the index?
body: SafeArea(
// child: (pages[currentIndex1]),
child: TabBarView(
children: <Widget>[
Home(),
Search(),
].toList(),
// controller: ,
),
),
bottomNavigationBar: BottomNavigationBar(
currentIndex: currentIndex1,
type: BottomNavigationBarType.shifting,
showUnselectedLabels: false,
showSelectedLabels: false,
items: [
BottomNavigationBarItem(
icon: Icon(Icons.home),
label: 'Home',
backgroundColor: Colors.blue),
BottomNavigationBarItem(
icon: Icon(Icons.search),
label: 'Search',
backgroundColor: Colors.blue),
],
you need to provide TabController on TabBarView, then you can switch tabItems using this controller.
you can check this example
import 'package:flutter/material.dart';
class Home extends StatelessWidget {
const Home({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Container(
child: Text("home"),
);
}
}
class Search extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
child: Text("Search"),
);
}
}
class NavTest extends StatefulWidget {
NavTest({Key? key}) : super(key: key);
#override
_NavTestState createState() => _NavTestState();
}
class _NavTestState extends State<NavTest> with SingleTickerProviderStateMixin {
final widgets = [
Home(),
Search(),
];
int currentIndex1 = 0;
late TabController controller;
#override
void initState() {
super.initState();
controller = TabController(length: widgets.length, vsync: this);
}
#override
void dispose() {
controller.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
// child: (pages[currentIndex1]),
child: TabBarView(
children: widgets,
controller: controller,
),
),
bottomNavigationBar: BottomNavigationBar(
currentIndex: currentIndex1,
type: BottomNavigationBarType.shifting,
showUnselectedLabels: false,
showSelectedLabels: false,
items: [
BottomNavigationBarItem(
icon: Icon(Icons.home),
label: 'Home',
backgroundColor: Colors.blue,
),
BottomNavigationBarItem(
icon: Icon(Icons.search),
label: 'Search',
backgroundColor: Colors.blue,
),
],
onTap: (value) {
setState(() {
// currentIndex1 = value;
controller.index = value;
});
},
),
);
}
}

Flutter: value of currentIndex property in BottomNavigationBar doesn't update when the state updates

I have a BottomNavigationBar that navigates to other pages when pressing an icon. This works fine, except the value of the currentIndex property in BottomNavigationBar doesn't update when the state updates, which means there is no change on the acual BottomNavigationBar. enter image description here
I'm using a vaiable (_selectedPage) to keep track of the selected index in the BottomNavigationBar, and the value changes when tapping an item, but it's not updating the currentIndex property when the state updates.. why is that?
import 'package:flutter/material.dart';
import 'package:independentproject/pages/home_page.dart';
import 'package:independentproject/pages/cook_recipe.dart';
class PageNavigationBar extends StatefulWidget {
#override
_PageNavigationBarState createState() => _PageNavigationBarState();
}
class _PageNavigationBarState extends State<PageNavigationBar> {
//default page showing in bottom navigation bar will be CookRecipe()
int _selectedPage = 1;
//all pages optional in bottom navigation bar
final List<Widget> _pageOptions = [
HomePage(),
CookRecipe(),
];
void onTapped(int pageTapped) {
setState(() {
//print(pageTapped);
_selectedPage = pageTapped;
Navigator.push(context, MaterialPageRoute(builder: (context) => _pageOptions[pageTapped]));
//print(_selectedPage);
});
}
#override
Widget build(BuildContext context) {
return BottomNavigationBar(
//TODO: currentIndex: doesn't update when the state updates, why?
currentIndex: _selectedPage,
//items showing in bottom navigation bar
items: [
BottomNavigationBarItem(
icon: Icon(Icons.home),
title: Text('Homepage'),
),
BottomNavigationBarItem(
icon: Icon(Icons.search),
title: Text('Search recipe'),
),
],
onTap: (int pageTapped) {
onTapped(pageTapped);
},
);
}
}
import 'package:flutter/material.dart';
import 'package:independentproject/page_navigation_bar.dart';
class HomePage extends StatefulWidget {
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Home page'),
),
body: Center(
child: Text('Home page'),
),
bottomNavigationBar: PageNavigationBar(),
),
);
}
}
import 'package:flutter/material.dart';
import 'package:independentproject/page_navigation_bar.dart';
class CookRecipe extends StatefulWidget {
#override
_CookRecipeState createState() => _CookRecipeState();
}
class _CookRecipeState extends State<CookRecipe> {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Search recipe'),
),
body: Center(
child: Text('Search recipes'),
),
bottomNavigationBar: PageNavigationBar(),
),
);
}
}
I would advise you to create a widget that will contain the BottomNavigationBar and also PageView that would allow you to switch pages with PageController.
For example:
class _MainScreenState extends State<MainScreen> {
PageController _pageController;
int _page = 1;
Duration pageChanging = Duration(milliseconds: 300);//this is for page animation-not necessary
Curve animationCurve = Curves.linear;//this is for page animation-not necessary
_MainScreenState();
#override
void initState() {
super.initState();
_pageController = PageController(initialPage: 1);
}
Widget build(BuildContext context) {
return Scaffold(
body: PageView(
physics: BouncingScrollPhysics(),
scrollDirection: Axis.horizontal,
controller: _pageController,
onPageChanged: onPageChanged,
children: <Widget>[
//here are all the pages you need:
//CookRecipe(),
],
),
bottomNavigationBar: BottomNavigationBar(
type: BottomNavigationBarType.fixed,
items: <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(
Icons.message,
),
title: Container(height: 0.0),
),
BottomNavigationBarItem(
icon: Icon(
Icons.home,
),
title: Container(height: 0.0),
),
BottomNavigationBarItem(
icon: Icon(
Icons.person,
),
title: Container(height: 0.0),
),
],
onTap: navigationTapped,
selectedItemColor: Theme.of(context).backgroundColor,
currentIndex: _page,
),
),
);
}
void navigationTapped(int page) {
_pageController.animateToPage(page,duration: pageChanging,
curve: animationCurve,);
}
#override
void dispose() {
super.dispose();
_pageController.dispose();
}
void onPageChanged(int page) {
if (this.mounted){
setState(() {
this._page = page;
});
}}
You can also do this without the PageView,and use only the controller to switch pages.
BTW-you create new instance of the navigation bar when you load a page which is bad practice
it is because PageNavigationBar is a own class, when you call there a setstate only this class updates
take a look at the Provider
a very usefull state management Package
or you can also handle your Page, when the NavBar is your Main Page and you have only one Page
return MaterialApp(
home: Scaffold(
appBar: ownAppBar(_selectedPage),
body: _bodyOptions[_selectedPage],
bottomNavigationBar: BottomNavigationBar(
currentIndex: _selectedPage,
items: [
BottomNavigationBarItem(
icon: Icon(Icons.home),
title: Text('Homepage'),
),
BottomNavigationBarItem(
icon: Icon(Icons.search),
title: Text('Search recipe'),
),
],
onTap: (int pageTapped) {
onTapped(pageTapped);
},
)
),
);
final List<Widget> _bodyOptions = [
HomePage(),
CookRecipe(),
];
You don't need to use Navigator to change pages, I modified your code just try.
import 'package:flutter/material.dart';
main() {
runApp(MaterialApp(home: PageNavigationBar()));
}
class PageNavigationBar extends StatefulWidget {
#override
_PageNavigationBarState createState() => _PageNavigationBarState();
}
class _PageNavigationBarState extends State<PageNavigationBar> {
//default page showing in bottom navigation bar will be CookRecipe()
int _selectedPage = 1;
//all pages optional in bottom navigation bar
final List<Widget> _pageOptions = [
HomePage(),
CookRecipe(),
];
void onTapped(int pageTapped) {
setState(() {
//print(pageTapped);
_selectedPage = pageTapped;
// Navigator.push(context, MaterialPageRoute(builder: (context) => _pageOptions[pageTapped]));
//print(_selectedPage);
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: _pageOptions[_selectedPage],
bottomNavigationBar: BottomNavigationBar(
//TODO: currentIndex: doesn't update when the state updates, why?
currentIndex: _selectedPage,
//items showing in bottom navigation bar
items: [
BottomNavigationBarItem(
icon: Icon(Icons.home),
title: Text('Homepage'),
),
BottomNavigationBarItem(
icon: Icon(Icons.search),
title: Text('Search recipe'),
),
],
onTap: (int pageTapped) {
onTapped(pageTapped);
},
),
);
}
}
class CookRecipe extends StatefulWidget {
#override
_CookRecipeState createState() => _CookRecipeState();
}
class _CookRecipeState extends State<CookRecipe> {
#override
Widget build(BuildContext context) {
return Center(
child: Text('Search recipes'),
);
}
}
class HomePage extends StatefulWidget {
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
#override
Widget build(BuildContext context) {
return Center(
child: Text('Home page'),
);
}
}

How to add drawer in bottom navigation bar in flutter?

I want to show a drawer when user clicks on the 4th(more_vert) icon, but I am not able to implement it. In my current implementation when 4th icon is clicked flutter takes me to a new page and there shows the drawer not over the current screen as it should. What am I doing wrong ? Also what is the differnce between BottomNavigationBar and BottomAppBar I could not find the difference anywhere. I checked out a few articles and it I think BottomAppBar is used to show the Fab floating in the bottom appbar. Is there any other difference between the two and when should one use one over the other.
class Home extends StatefulWidget {
#override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
List<Widget> _widgetOptions = <Widget>[
Page1(),
Page2(),
Page3(),
Page4(), // this page implements the drawer
];
int _currentSelected = 0;
void _onItemTapped(int index) {
setState(() {
_currentSelected = index;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: _widgetOptions.elementAt(_currentSelected),
bottomNavigationBar: BottomNavigationBar(
type: BottomNavigationBarType.fixed,
onTap: _onItemTapped,
currentIndex: _currentSelected,
showUnselectedLabels: true,
unselectedItemColor: Colors.grey[800],
selectedItemColor: Color.fromRGBO(10, 135, 255, 1),
items: <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(AntDesign.carryout),
),
BottomNavigationBarItem(
icon: Icon(MaterialCommunityIcons.sack),
),
BottomNavigationBarItem(
icon: Icon(Octicons.archive),
),
BottomNavigationBarItem(
icon: Icon(Icons.more_vert),
)
],
),
// backgroundColor: Colors.black,
);
}
}
You don't need an extra page for that.
You could do it like that:
class Home extends StatefulWidget {
#override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
List<Widget> _widgetOptions = <Widget>[
Page(),
Page(),
Page(),
];
int _currentSelected = 0;
GlobalKey<ScaffoldState> _drawerKey = GlobalKey();
void _onItemTapped(int index) {
index == 3
? _drawerKey.currentState.openDrawer()
: setState(() {
_currentSelected = index;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
key: _drawerKey,
body: _widgetOptions.elementAt(_currentSelected),
drawer: Drawer(),
bottomNavigationBar: BottomNavigationBar(
type: BottomNavigationBarType.fixed,
onTap: _onItemTapped,
currentIndex: _currentSelected,
showUnselectedLabels: true,
unselectedItemColor: Colors.grey[800],
selectedItemColor: Color.fromRGBO(10, 135, 255, 1),
items: <BottomNavigationBarItem>[
BottomNavigationBarItem(
title: Text('Page 1'),
icon: Icon(Icons.access_alarm),
),
BottomNavigationBarItem(
title: Text('Page 2'),
icon: Icon(Icons.accessible),
),
BottomNavigationBarItem(
title: Text('Page 3'),
icon: Icon(Icons.adb),
),
BottomNavigationBarItem(
title: Text('Drawer'),
icon: Icon(Icons.more_vert),
)
],
),
);
}
}
class Page extends StatelessWidget {
const Page({Key key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Container();
}
}
Adding a GlobalKey for the Scaffold which implements the drawer and implementing the Drawer in your root Scaffold.
The BottomNavigationBar doesn't show the drawer icon like the AppBar does.
To open the drawer programmatically :
Create this variable as state :
GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey();
Set it as the Scaffold's key :
Scaffold(
key: _scaffoldKey,
Then, you can use the key state to open the drawer :
_scaffoldKey.currentState.openDrawer();
The solutions provided above work if you are not using the newer versions of Flutter with Null Safety. In case you are using Flutter 2.0 or greater. Due to Null Safety, you will get an error saying:
The method 'openDrawer' can't be unconditionally invoked because the receiver can be 'null'.
Try making the call conditional (using '?.') or adding a null check to the target
Use: _drawerKey.currentState!.openDrawer();

How to use BottomNavigationBar with Navigator?

The Flutter Gallery example of BottomNavigationBar uses a Stack of FadeTransitions in the body of the Scaffold.
I feel it would be cleaner (and easier to animate) if we could switch pages by using a Navigator.
Are there any examples of this?
int index = 0;
#override
Widget build(BuildContext context) {
return new Scaffold(
body: new Stack(
children: <Widget>[
new Offstage(
offstage: index != 0,
child: new TickerMode(
enabled: index == 0,
child: new MaterialApp(home: new YourLeftPage()),
),
),
new Offstage(
offstage: index != 1,
child: new TickerMode(
enabled: index == 1,
child: new MaterialApp(home: new YourRightPage()),
),
),
],
),
bottomNavigationBar: new BottomNavigationBar(
currentIndex: index,
onTap: (int index) { setState((){ this.index = index; }); },
items: <BottomNavigationBarItem>[
new BottomNavigationBarItem(
icon: new Icon(Icons.home),
title: new Text("Left"),
),
new BottomNavigationBarItem(
icon: new Icon(Icons.search),
title: new Text("Right"),
),
],
),
);
}
You should keep each page by Stack to keep their state.
Offstage stops painting, TickerMode stops animation.
MaterialApp includes Navigator.
Output:
Code:
int _index = 0;
#override
Widget build(BuildContext context) {
Widget child;
switch (_index) {
case 0:
child = FlutterLogo();
break;
case 1:
child = FlutterLogo(colors: Colors.orange);
break;
case 2:
child = FlutterLogo(colors: Colors.red);
break;
}
return Scaffold(
body: SizedBox.expand(child: child),
bottomNavigationBar: BottomNavigationBar(
onTap: (newIndex) => setState(() => _index = newIndex),
currentIndex: _index,
items: [
BottomNavigationBarItem(icon: Icon(Icons.looks_one), title: Text("Blue")),
BottomNavigationBarItem(icon: Icon(Icons.looks_two), title: Text("Orange")),
BottomNavigationBarItem(icon: Icon(Icons.looks_3), title: Text("Red")),
],
),
);
}
Here is an example how you can use Navigator with BottomNavigationBar to navigate different screen.
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
// This navigator state will be used to navigate different pages
final GlobalKey<NavigatorState> _navigatorKey = GlobalKey<NavigatorState>();
int _currentTabIndex = 0;
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
body: Navigator(key: _navigatorKey, onGenerateRoute: generateRoute),
bottomNavigationBar: _bottomNavigationBar(),
),
);
}
Widget _bottomNavigationBar() {
return BottomNavigationBar(
type: BottomNavigationBarType.fixed,
items: [
BottomNavigationBarItem(
icon: Icon(Icons.home),
title: Text("Home"),
),
BottomNavigationBarItem(
icon: Icon(Icons.account_circle), title: Text("Account")),
BottomNavigationBarItem(
icon: Icon(Icons.settings),
title: Text("Settings"),
)
],
onTap: _onTap,
currentIndex: _currentTabIndex,
);
}
_onTap(int tabIndex) {
switch (tabIndex) {
case 0:
_navigatorKey.currentState.pushReplacementNamed("Home");
break;
case 1:
_navigatorKey.currentState.pushReplacementNamed("Account");
break;
case 2:
_navigatorKey.currentState.pushReplacementNamed("Settings");
break;
}
setState(() {
_currentTabIndex = tabIndex;
});
}
Route<dynamic> generateRoute(RouteSettings settings) {
switch (settings.name) {
case "Account":
return MaterialPageRoute(builder: (context) => Container(color: Colors.blue,child: Center(child: Text("Account"))));
case "Settings":
return MaterialPageRoute(builder: (context) => Container(color: Colors.green,child: Center(child: Text("Settings"))));
default:
return MaterialPageRoute(builder: (context) => Container(color: Colors.white,child: Center(child: Text("Home"))));
}
}
}
Here is example:
int _currentIndex = 0;
Route<Null> _getRoute(RouteSettings settings) {
final initialSettings = new RouteSettings(
name: settings.name,
isInitialRoute: true);
return new MaterialPageRoute<Null>(
settings: initialSettings,
builder: (context) =>
new Scaffold(
body: new Center(
child: new Container(
height: 200.0,
width: 200.0,
child: new Column(children: <Widget>[
new Text(settings.name),
new FlatButton(onPressed: () =>
Navigator.of(context).pushNamed(
"${settings.name}/next"), child: new Text("push")),
],
))
),
bottomNavigationBar: new BottomNavigationBar(
currentIndex: _currentIndex,
onTap: (value) {
final routes = ["/list", "/map"];
_currentIndex = value;
Navigator.of(context).pushNamedAndRemoveUntil(
routes[value], (route) => false);
},
items: [
new BottomNavigationBarItem(
icon: new Icon(Icons.list), title: new Text("List")),
new BottomNavigationBarItem(
icon: new Icon(Icons.map), title: new Text("Map")),
]),
));
}
#override
Widget build(BuildContext context) =>
new MaterialApp(
initialRoute: "/list",
onGenerateRoute: _getRoute,
theme: new ThemeData(
primarySwatch: Colors.blue,
),
);
You can set isInitialRoute to true and pass it to MaterialPageRoute. It will remove pop animation.
And to remove old routes you can use pushNamedAndRemoveUntil
Navigator.of(context).pushNamedAndRemoveUntil(routes[value], (route) => false);
To set current page you can have a variable in your state _currentIndex and assign it to BottomNavigationBar:
Glad You asked, I experimented with this a couple of months back and tried to simplify this through a blog post. I won't be able to post the complete code here since it is pretty long, But I can certainly link all the resources to clarify it.
Everything about the BottomNavigationBar in flutter
complete sample code
Dartpad demo
If you prefer you can also depend on this package https://pub.dev/packages/navbar_router
Here's the resulting output of what the article helps you build
Navigator.of(context).pushNamedAndRemoveUntil(
routes[value], (route) => true);
I had to use true to enable back button.
NB: I was using Navigator.pushNamed() for navigation.
This is the code I am using in my project. If you try to avoid page viewer so you can try this
import 'package:flutter/material.dart';
class Dashboard extends StatefulWidget {
const Dashboard({Key? key}) : super(key: key);
#override
State<Dashboard> createState() => _DashboardState();
}
class _DashboardState extends State<Dashboard> {
int _selectedIndex = 0;
void _onItemTapped(int index) {
setState(() {
_selectedIndex = index;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Sample'),
),
body: SingleChildScrollView(
child: Column(
children: [
if (_selectedIndex == 0)
// you can call custom widget here
Column(
children: const [
Text("0"),
],
)
else if (_selectedIndex == 1)
Column(
children: const [
Text("1"),
],
)
else
Column(
children: const [
Text("2"),
],
),
],
),
),
bottomNavigationBar: BottomNavigationBar(
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(Icons.headphones),
label: 'Home',
),
BottomNavigationBarItem(
icon: Icon(Icons.business),
label: 'Business',
),
BottomNavigationBarItem(
icon: Icon(Icons.school),
label: 'School',
),
],
currentIndex: _selectedIndex,
selectedItemColor: Colors.amber[800],
unselectedItemColor: Colors.grey,
onTap: _onItemTapped,
),
);
}
}
Happy Coding