For my flutter project, I am using google_nav_bar. Every time I click on a button in the nav_bar I want to navigate to another page. I want to do this without making the nav bar my home page and loading other pages to the nav bar.
import 'package:flutter/material.dart';
import 'package:google_nav_bar/google_nav_bar.dart';
import 'package:space_flight_recorder/view/home.dart';
import '../view/about.dart';
import '../view/upcoming.dart';
import '../view/previous.dart';
class Nav_bar extends StatefulWidget {
const Nav_bar({super.key});
#override
State<Nav_bar> createState() => _Nav_barState();
}
class _Nav_barState extends State<Nav_bar> {
bool status = false;
int index = 0;
#override
Widget build(BuildContext context) {
return
// body: _pages[_index],
SingleChildScrollView(
// scrollDirection: Axis.horizontal,
child: GNav(
// onTabChange: (index) {
// setState(() {
// _index = index;
// });
// },
curve: Curves.easeInOut,
backgroundColor: Colors.black,
color: Colors.white,
activeColor: Colors.blue,
tabBackgroundColor: Colors.transparent,
gap: 3,
hoverColor: Colors.grey,
iconSize: 30,
tabs: [
GButton(
text: 'HOME',
icon: Icons.home,
onPressed:(){
index=1;
},
),
GButton(
text: 'PREVIOUS',
icon: Icons.restart_alt,
onPressed:(){
index=2;
},
),
GButton(
text: 'UPCOMING',
icon: Icons.rocket_launch,
onPressed:(){
index=3;
},
),
GButton(
text: 'ABOUT',
icon: Icons.info,
onPressed:(){
index=4;
},
),
],
onTabChange: pagechange(),
),
);
}
pagechange() {
if (index==1)
{
Navigator.pushNamed(context, 'home');
}
if (index==2)
{
Navigator.pushNamed(context, 'previous');
}
if (index==3)
{
Navigator.pushNamed(context, 'upcoming');
}
if (index==4)
{
Navigator.pushNamed(context, 'info');
}
}
}
I have also set the bottom navbar in all of the pages that I navigate to as follows
bottomNavigationBar: Nav_bar(),
In this code, the page is not changing, and when I write the Navigator.pushedName function in the onPressed function itself, then page is changed but the animation at the bottom is absent, it just gets stuck at home.
All I want is to change the page as we click the button and change the animation of the nav bar with it without making the bottom nav bar class as my page which in turns load all the other pages using setState() etc.
I am using this dependency
google_nav_bar: ^5.0.6
You've forgot to call setState like
GButton(
text: 'HOME',
icon: Icons.home,
onPressed:(){
setState((){
index=1;
});
},
),
Related
I have question I hope to help me How can I call the binding of page Home when I press the tap of home on bottom navbar
**Controller of bottom navbar **
class BottomNavBarController extends GetxController{
List bodyPage=[
const Home(),
const Settings(),
const ProfileView()
];
NavBar
body:Obx(()=> navBarController.currentPage,
),
// bodyPage[navBarController.indexNavBar],
bottomNavigationBar:Obx(()=> NavigationBar(
currentIndex: navBarController.indexNavBar.value,
items: [
NavigationBarItem(
icon: const Icon(home_outline, ),
),
NavigationBarItem(
icon: const Icon(setting_outline),
),
NavigationBarItem(
icon: const Icon(menu_outline),
)])));
**Binding **
class HomeBinding implements Bindings{
#override
void dependencies() {
Get.put(HomeController());
}}
**Get Page **
getPages: [
GetPage(name: "/home", page:()=> const HomeView(), binding:HomeBinding()),
]
I use bottom navigation and Getx.
In this way :
changeNavigationIndex(int index) {
myPresenter.setMainNavigationIndex(index);
switch (index) {
case 1:
setState(() {
mainNavigationTitle = txtTitle2;
});
break;
case 2:
setState(() {
mainNavigationTitle = txtTitle3;
});
break;
case 3:
setState(() {
mainNavigationTitle = txtTitle4;
});
break;
case 0:
default:
setState(() {
mainNavigationTitle = txtTitle1;
});
break;
}
}
buildBottomNavigationMenu(context, MyPresenter myPresenter) {
changeNavigationIndex(myPresenter.mainNavigationIndex);
return Obx(() =>
MediaQuery(
data: MediaQuery.of(context).copyWith(textScaleFactor: 1.0),
child: SizedBox(
child: BottomNavigationBar(
onTap: changeNavigationIndex,
type: BottomNavigationBarType.fixed,
currentIndex: salesPresenter.mainNavigationIndex,
selectedIconTheme: IconThemeData(
color: CustomColors.iconColor,
size: 30,
),
items: [
BottomNavigationBarItem(
icon: const Icon(Icons.icon1),
label: txt1,
backgroundColor: Theme.of(context).primaryColor,
),
BottomNavigationBarItem(
icon: const Icon(Icons.icon2),
label: txt2,
backgroundColor: Theme.of(context).primaryColor,
),
BottomNavigationBarItem(
icon: const Icon(Icons.icon3),
label: txt3,
backgroundColor: Theme.of(context).primaryColor,
),
BottomNavigationBarItem(
icon: const Icon(Icons.icon4),
label: txt4,
backgroundColor: Theme.of(context).primaryColor,
),
],
),
)
));
}
return
WillPopScope(
onWillPop: () async => false,
child: Scaffold(
body:
: GetX<MyPresenter>(
builder: (mp) => IndexedStack(
index: mp.mainNavigationIndex,
children: const[
Screen1(),
Screen2(),
Screen3(),
Screen4(),
],
)
),
bottomNavigationBar: buildBottomNavigationMenu(context, myPresenter),
drawer: const MainDrawerWidget(),
),
);
So, In this app all Getx Binding is in separated file (MainBind.dart) That I call on Main.dart.
But if you want call the bind in same file that u have programmated the bottom navigation, you can put the bind in your Main Class like this:
class _MainScreenState extends State<MainScreen> {
Get.lazyPut<MyPresenter>(() => MyPresenter(), fenix: true);
}
I have a MainPage with bottomnavigation bar with bottomnavigation items. I want to call APIs of bottomnavigation item pages whenever i tap on it i.e I want to reload page everytime I vist the page.
But in my case its not reloading everytime but at once when mainpage called all api of bottomnavigation items page APIs are called attime.
MainPage
class MainPage extends StatefulWidget{
#override
_MainPageState createState() => new _MainPageState();
}
class _MainPageState extends State<MainPage>{
ListQueue<int> _navigationQueue = ListQueue();
int _selectedIndex = 0;
int counter = Constant.CART_COUNT;
List<GlobalKey<NavigatorState>> _navigatorKeys = [
GlobalKey<NavigatorState>(),
GlobalKey<NavigatorState>(),
GlobalKey<NavigatorState>(),
GlobalKey<NavigatorState>()
];
Future<void> secureScreen() async {
await FlutterWindowManager.addFlags(FlutterWindowManager.FLAG_SECURE);
}
#override
void initState() {
// TODO: implement initState
super.initState();
secureScreen();
}
#override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: () async {
if (_navigationQueue.isEmpty) return true;
setState(() {
_navigationQueue.removeLast();
int position = _navigationQueue.isEmpty ? 0 : _navigationQueue.last;
_selectedIndex = position;
});
return false;
},
child: Scaffold(
backgroundColor: Colors.white,
bottomNavigationBar: BottomNavigationBar(
type: BottomNavigationBarType.fixed,
currentIndex: _selectedIndex,
selectedItemColor: Colors.blueAccent,
showSelectedLabels: true,
showUnselectedLabels: false,
items: [
BottomNavigationBarItem(
icon: Icon(
FontAwesome.home,
color: Colors.grey,
),
label: 'Home',
activeIcon: Icon(
FontAwesome.home,
color: Colors.blueAccent,
),
),
BottomNavigationBarItem(
icon: Icon(
FontAwesome.product_hunt,
color: Colors.grey,
),
label: 'Products',
activeIcon: Icon(
FontAwesome.product_hunt,
color: Colors.blueAccent,
),
),
BottomNavigationBarItem(
icon: Icon(
FontAwesome.users,
color: Colors.grey,
),
label: 'Customers',
activeIcon: Icon(
FontAwesome.users,
color: Colors.blueAccent,
),
),
BottomNavigationBarItem(
icon: Icon(
FontAwesome.search_plus,
color: Colors.grey,
),
label: 'Order Details',
activeIcon: Icon(
FontAwesome.users,
color: Colors.blueAccent,
),
),
],
onTap: (index) {
if(_selectedIndex == _selectedIndex){
_navigationQueue.removeWhere((element) => element == index);
_navigationQueue.addLast(index);
setState(() {
this._selectedIndex = index;
});
}
},
),
body: Stack(
children: [
_buildOffstageNavigator(0),
_buildOffstageNavigator(1),
_buildOffstageNavigator(2),
_buildOffstageNavigator(3)
],
),
),
);
}
Map<String, WidgetBuilder> _routeBuilders(BuildContext context, int index) {
return {
'/': (context) {
return [
HomePage(),
ProductSearchPage(),
CustomerPage(),
OrdersPage()
].elementAt(index);
},
};
}
Widget _buildOffstageNavigator(int index) {
var routeBuilders = _routeBuilders(context, index);
return Offstage(
offstage: _selectedIndex != index,
child: Navigator(
key: _navigatorKeys[index],
onGenerateRoute: (routeSettings) {
return MaterialPageRoute(
builder: (context) => routeBuilders[routeSettings.name]!(context),
);
},
),
);
}
}
You have used an offstage widget which will just remove the ui from the stage. It wont reload when the index is changed. You have to create a list
List screens = [
HomePage(),
ProductSearchPage(),
CustomerPage(),
OrdersPage()
],
//Then in body use
body: screens[index]
You can set the api call in on Tap because all the pages will be initialized at a time that's why you are facing this issue.
Just check the condition on Tap for a currently selected index and write down the API call there.
I want to navigate to a page when I click navbar items. I tried this using a gesture detector widget. but it's not working here. and for one icon I want to add a snack bar to display coming soon. how can I do this. appreciate your help on this.
navigate to a page
display snack bar with the text "coming soon"
class BottomNavigation extends StatefulWidget {
const BottomNavigation({ Key? key }) : super(key: key);
#override
State<BottomNavigation> createState() => _BottomNavigationState();
}
class _BottomNavigationState extends State<BottomNavigation> {
int _selectedindex = 0;
void _navigatePages(int index) {
setState(() {
_selectedindex = index;
});
}
final List<Widget> _Pages = [const Dashboard() ,const WelcomeScreen()];
#override
Widget build(BuildContext context) {
return Scaffold(
extendBody: true,
body: _Pages[_selectedindex],
bottomNavigationBar: Container(
clipBehavior: Clip.hardEdge,
decoration: BoxDecoration(
borderRadius: BorderRadius.only(
topRight: Radius.circular(24),
topLeft: Radius.circular(24),
),
// color: Colors.transparent,
),
child: BottomNavigationBar(
backgroundColor: Colors.grey.withOpacity(0.6),
currentIndex: _selectedindex,
onTap: _navigatePages,
type: BottomNavigationBarType.fixed,
items: const [
BottomNavigationBarItem(
icon: ImageIcon(
AssetImage("assets/images/wallet.png"),
color: Colors.black,
size: 32,
),
label: "",
),
BottomNavigationBarItem(
icon: ImageIcon(
AssetImage("assets/images/store.png"),
color: Colors.black,
size: 32,
),
label: "",
),
BottomNavigationBarItem(
icon: ImageIcon(
AssetImage("assets/images/coin.png"),
color: Colors.black,
size: 32,
),
label: "",
)
]),
),
);
}
}
I didn't understand if you can navigate to a screen or not, but I copied your code as is and I can navigate, anyway I leave you this little change that you can do if you can't go to another page:
BottomNavigationBar(
backgroundColor: Colors.grey.withOpacity(0.6),
currentIndex: _selectedindex,
onTap: (int i) => _navigatePages(i), // here
type: BottomNavigationBarType.fixed,
items: const [
[...]
Now, to show a Snackbar, in your function _navigatePages you only make a small validation that if the index is the last one (that is the 2), show the snackbar, first hide one if it exists... if not do the setState.
void _navigatePages(int index) {
if (index == 2) {
ScaffoldMessenger.of(context).hideCurrentSnackBar();
ScaffoldMessenger.of(context)
.showSnackBar(const SnackBar(content: Text("coming soon")));
} else {
setState(() {
_selectedindex = index;
});
}
}
Your full code is ok, just you need to add a Snackbar for your needed index. Suppose, you have three Bottom Navigation Bar & you will show your snackbar for the last Bottom Navigation icon, which means the index will be 2. [this index will be changed based on your decision]
Your _navigatePages() function will be changed like as below code :
void _navigatePages(int index) {
if(index == 2){
ScaffoldMessenger.of(context).hideCurrentSnackBar();
ScaffoldMessenger.of(context)
.showSnackBar(const SnackBar(content: Text("coming soon")));
}else{
ScaffoldMessenger.of(context).hideCurrentSnackBar();
setState(() {
_selectedindex = index;
});
}
}
N.B: Please change the function only, others all code is ok.
I have 4 pages in bottom navigation bar. I am facing a problem related to route that i want to route to a specific page in bottom navigation bar from another page?
e.g I am going to login page and post successful login I want to route user to accountdetails(AccountSetting) but if I am selecting account setting then in that page bottom navigation bar is not showing and if I am routing to bottom nav bar here I am unable to select index of my choice. How can I select index of my choice because I don't want to make new page having bottom nav bar?
class BottomNavBar extends StatefulWidget {
static String routeName = "/bottombar";
#override
_BottomNavBarState createState() => _BottomNavBarState();
}
class _BottomNavBarState extends State<BottomNavBar> {
CartCountController cartCountController = CartCountController();
DoublePressBackBotton doublePressBackBotton = DoublePressBackBotton();
int _selectedIndex = 0;
#override
void initState() {
Future.delayed(Duration(milliseconds: 1000)).then((value) {
cartCountController.cartItemCount();
});
super.initState();
}
#override
void dispose() {
Future.delayed(Duration(milliseconds: 1000)).then((value) {
cartCountController.cartItemCount();
});
super.dispose();
}
List _widgetOptions = [
HomeScreen(),
CategoryList(),
InviteFriend(),
AccountSetting(),
];
void _onItemTapped(
int index,
) {
setState(() {
_selectedIndex = index;
});
}
#override
Widget build(BuildContext context) {
return
// drawer: SideDrawer(),
body: WillPopScope(
child: _widgetOptions.elementAt(_selectedIndex),
onWillPop: () {
return doublePressBackBotton.doubleBack();
},
),
bottomNavigationBar: BottomNavigationBar(
// backgroundColor: Color(0xff202020),
items: <BottomNavigationBarItem>[
BottomNavigationBarItem(
backgroundColor: kPrimaryColor,
icon: Icon(
Icons.home_outlined,
color: Colors.white,
),
label: 'Home',
),
BottomNavigationBarItem(
backgroundColor: kPrimaryColor,
icon: Icon(
Icons.category,
color: Colors.white,
),
label: 'Category',
),
BottomNavigationBarItem(
backgroundColor: kPrimaryColor,
icon: ImageIcon(
AssetImage(AppImages.phonecall),
color: Colors.white,
),
label: 'Invite',
),
BottomNavigationBarItem(
backgroundColor: kPrimaryColor,
icon: Icon(
Icons.person_outlined,
color: Colors.white,
),
label: 'Account',
),
],
// fixedColor: Colors.black,
currentIndex: _selectedIndex,
// selectedItemColor: Color(0xffF9C000),
onTap: _onItemTapped,
showUnselectedLabels: true,
selectedItemColor: kPrimaryLightColor,
// unselectedItemColor: Color(0xff737373),
unselectedLabelStyle: GoogleFonts.lato(color: Colors.white),
selectedLabelStyle: GoogleFonts.lato(color: Colors.white),
),
);
// );
}
}
I am using flutter's bottom navigation bar. On tapping the navbar icons, the text get larger. But it's way bit large for me as you can see in the image below.
Flutter Bottom Navigation Bar Image
I want to control the on tap text large size and make it a bit smaller. How can I do that in flutter?
Here's the code:
import 'package:flutter/material.dart';
import 'package:adminify/pages/PageOne.dart';
import 'package:adminify/pages/PageTwo.dart';
import 'package:adminify/pages/PageThree.dart';
import 'package:adminify/pages/PageFour.dart';
import 'package:adminify/pages/PageFive.dart';
class HomeScreen extends StatefulWidget {
#override
_HomeScreenState createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> with TickerProviderStateMixin {
int _currentIndex = 0;
#override
void initState() {
super.initState();
}
void navigationTapped(int page) {
setState(() {
_currentIndex = page;
});
}
#override
Widget build(BuildContext context) {
// this is all pages here in list we can choose index when click bottom navigation bar
List<Widget> _allPages = [
PageOne(),
PageTwo(),
PageTree(),
PageFour(),
PageFive(),
];
return Scaffold(
body: _allPages[_currentIndex],
bottomNavigationBar: buildBottomNavigationBar(),
);
}
// Bottom navigation bar area you can choose icons what you want.
BottomNavigationBar buildBottomNavigationBar() {
return BottomNavigationBar(
type: BottomNavigationBarType.fixed,
fixedColor: Colors.red,
currentIndex: _currentIndex,
onTap: navigationTapped,
// iconSize: 28,
items: [
BottomNavigationBarItem(
icon: Icon(Icons.home),
title: Text(
"Home",
style: TextStyle(fontWeight: FontWeight.normal),
),
),
BottomNavigationBarItem(
icon: Icon(
Icons.explore,
),
title: Text(
"Admission",
style: TextStyle(fontWeight: FontWeight.normal),
),
),
BottomNavigationBarItem(
icon: Icon(Icons.cloud),
title: Text(
"University",
style: TextStyle(fontWeight: FontWeight.normal),
overflow: TextOverflow.clip,
textAlign: TextAlign.center,
),
),
BottomNavigationBarItem(
icon: Icon(Icons.person),
title: Text(
"Favorites",
style: TextStyle(fontWeight: FontWeight.normal),
),
),
BottomNavigationBarItem(
icon: Icon(Icons.verified_user),
title: Text(
"Profile",
style: TextStyle(fontWeight: FontWeight.normal),
),
),
],
);
}
}
There is a property selectedFontSize on the BottomNavigationBar.
You can use this one. Simply set the size (interger) to the desired value.
Additionaly; there is also a unselectedFontSize on the BottomNavigationBar, ther you can set all the title-fontsize attonce to the desired size.
bottomNavigationBar: BottomNavigationBar(
currentIndex: index,
onTap: (int index) {
setState(() {
this.index = index;
});
},
backgroundColor: Colors.white,
type: BottomNavigationBarType.fixed,
selectedFontSize: 12,
unselectedFontSize: 12,
items: [
BottomNavigationBarItem(
icon: ClipOval(
child: Container(
color:
omitted ...
if you check the source code of the bottom_navigation_bar.dart, you will see that the active font size of the bottom navigation bar is fixed, it is written as follows:
const double _kActiveFontSize = 14.0;
if you want to change this, I think you need to create your own custom bottom navigation bar to the active font size that you want.
From having a short look into the BottomNavigationBar code, you can't. It seems that it uses the hardcoded _kActiveFontSize which is set to 14. Check bottom_navigation_bar.dart line 366 for FixedLabel style or line 411 for ShiftingLabel style. You may want to create an issue to get that fixed https://github.com/flutter/flutter/issues