Flutter- how to navigate different pages by curved navigation bar - flutter

i am creating a flutter app and want help on how to navigate to different pages. Also, when i tap on buttons of curved navigation bar nothing happens the icons not changing.
can u please help me out?
here is my code for the curved navigation bar
Thank u
import 'package:flutter/material.dart';
import 'package:hexcolor/hexcolor.dart';
class BAR extends StatefulWidget {
const BAR({super.key});
#override
State<BAR> createState() => _BARState();
}
class _BARState extends State<BAR> {
#override
Widget build(BuildContext context) {
return CurvedNavigationBar(
backgroundColor: HexColor("#F7ECCD"),
color: HexColor("#AE621C"),
items: [
Icon(
Icons.home,
color: Colors.white,
size: 30,
),
Icon(
Icons.favorite,
color: Colors.white,
size: 30,
),
Icon(
Icons.settings,
color: Colors.white,
size: 30,
)
],
onTap: (index){
setState(() {
if (index == 0) {
Navigator.pushNamed(context, '/');
}
if (index == 1) {
Navigator.pushNamed(context, '/one');
}
if (index == 2) {
Navigator.pushNamed(context, '/two');
}
});
},);
}
}

import 'package:flutter/cupertino.dart';
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _selectedIndex = 0;
static const TextStyle optionStyle =
TextStyle(fontSize: 30, fontWeight: FontWeight.bold);
static const List<Widget> _widgetOptions = <Widget>[
Text(
'Index 0: Home',
style: optionStyle,
),
Text(
'Index 1: Business',
style: optionStyle,
),
Text(
'Index 2: School',
style: optionStyle,
),
];
void _onItemTapped(int index) {
setState(() {
_selectedIndex = index;
});
}
#override
Widget build(BuildContext context) {
return CupertinoTabScaffold(
tabBar: CupertinoTabBar(
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(CupertinoIcons.home),
title: Text('Home'),
),
BottomNavigationBarItem(
icon: Icon(CupertinoIcons.business),
title: Text('Business'),
),
BottomNavigationBarItem(
icon: Icon(CupertinoIcons.school),
title: Text('School'),
),
],
currentIndex: _selectedIndex,
onTap: _onItemTapped,
backgroundColor: CupertinoColors.systemGrey,
activeColor: CupertinoColors.black,
),
tabBuilder: (BuildContext context, int index) {
return CupertinoTabView(
builder: (BuildContext context) {
return CupertinoPageScaffold(
child: Center(
child: _widgetOptions.elementAt(index),
),
);
},
);
},
);
}
}

Related

How to add scroll into bottom navigation bar items

I have implemented an app that navigates through a few screens. I have added the bottom navigation bar and 1st tab I add a page with list view items with sqlflite data.I can't scroll list view data. other tabs I have added to show another screen.
code is below.
//this is my homepage screen
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key});
#override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage>
with SingleTickerProviderStateMixin {
late List<LeaveModel> _leaveList = [];
final _userService = LeaveService();
int _selectedIndex = 0;
#override
void initState() {
getAllUserDetails();
super.initState();
}
void _onItemTapped(int index) {
setState(() {
_selectedIndex = index;
});
}
I have create botom navigation bar with 4 item.
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: IconButton(
icon: const Icon(Icons.menu),
onPressed: () {},
),
title: const Text('Leave Tracker'),
actions: <Widget>[
IconButton(
icon: const Icon(Icons.notifications),
onPressed: () {},
),
IconButton(
icon: const Icon(Icons.add_box),
onPressed: () {
Navigator.push(context,
MaterialPageRoute(builder: (context) => AddLeave()))
.then((data) {
if (data != null) {}
getAllUserDetails();
});
},
)
],
),
bottomNavigationBar: BottomNavigationBar(
type: BottomNavigationBarType.fixed,
currentIndex: _selectedIndex,
onTap: _onItemTapped,
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(Icons.man),
label: 'All',
),
BottomNavigationBarItem(
icon: Icon(Icons.sick_rounded),
label: 'Sick',
),
BottomNavigationBarItem(
icon: Icon(Icons.holiday_village),
label: 'Casual',
),
BottomNavigationBarItem(
icon: Icon(Icons.weekend),
label: 'Other',
),
],
),
From this 4 items goto different 3 screens.1st item link to same page.(HomePage())
body: Center(
child: _selectedIndex == 0
? myListView(context)
: _selectedIndex == 1
? AllSickLeave()
: _selectedIndex == 2
? AllCasualLeave()
: ViewOtherLeave(),
),
);
}
In HomePage() i have add listview and data taking from sqlflite database.
getAllUserDetails() async {
var users = await _userService.readAllLeave();
_leaveList = <LeaveModel>[];
users.forEach((leave) {
setState(() {
var leaveModel = LeaveModel();
leaveModel.id = leave['id'];
leaveModel.leaveType = leave['leaveType'];
leaveModel.leaveStartDate = leave['leaveStartDate'];
leaveModel.leaveEndDate = leave['leaveEndDate'];
leaveModel.reason = leave['reason'];
leaveModel.leaveDays = leave['leaveDays'];
_leaveList.add(leaveModel);
});
});
}
Widget myListView(BuildContext context) {
return Scaffold(
body: SingleChildScrollView(
child: Column(
children: [
SizedBox(
height: 5.0,
),
Text(
'All Leave Details',
style: TextStyle(fontSize: 20.0, fontWeight: FontWeight.bold),
),
ListView.builder(
shrinkWrap: true,
itemCount: _leaveList.length,
itemBuilder: (context, index) {
return Card(
child: ListTile(
title: Text(
'Leave Type : ${_leaveList[index].leaveType ?? ''}'),
subtitle: Text('Reason : ${_leaveList[index].reason}'),
trailing: Row(
mainAxisSize: MainAxisSize.min,
children: [
IconButton(
onPressed: () {},
icon: Icon(
Icons.edit,
color: Colors.teal,
)),
IconButton(
onPressed: () {},
icon: Icon(
Icons.delete,
color: Colors.red,
)),
],
),
),
);
}),
],
),
),
);
}
}
You dont need to have multiple scaffold, and try this format
Widget myListView(BuildContext context) {
return ListView.builder(
padding: EdgeInsets.only(top: 25),
itemCount: _leaveList.length + 1,
itemBuilder: (context, index) {
if (index == 0)
return Text(
'All Leave Details',
style: TextStyle(fontSize: 20.0, fontWeight: FontWeight.bold),
);
return Card(
child: ListTile(

Why can't I keep scroll position although I use PageStorageKey?

I have used NestedScrollView and SliverAppBar to hide app bar when scrolling. In the body of NestedScrollView, I have CustomScrollView with a PageStorageKey but when I have switched back to events tab, scroll position is lost. I cannot understand it. Could you please help me?
home_screen.dart
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:liveitup/app/screens/HomeScreen/drawer_icon.dart';
import 'package:liveitup/app/screens/HomeScreen/drawer_page.dart';
import 'package:liveitup/app/screens/HomeScreen/tabs/bottom_navigation.dart';
import 'package:liveitup/app/screens/HomeScreen/tabs/tab_item.dart';
import 'package:liveitup/app/screens/HomeScreen/tabs/tab_navigators/event_tab_navigator.dart';
import 'package:liveitup/app/screens/HomeScreen/tabs/tab_navigators/message_tab_navigator.dart';
import 'package:liveitup/app/screens/HomeScreen/tabs/tab_navigators/notification_tab_navigator.dart';
import 'package:liveitup/blocs/UserBloc/bloc.dart';
import '../../../constants.dart';
class HomeScreen extends StatefulWidget {
const HomeScreen({Key? key}) : super(key: key);
#override
_HomeScreenState createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
var _currentTab = TabItem.events;
void _selectTab(TabItem tabItem) {
setState(() => _currentTab = tabItem);
}
#override
Widget build(BuildContext context) {
var scaffoldKey = GlobalKey<ScaffoldState>();
UserBloc _userBloc = BlocProvider.of<UserBloc>(context);
return Scaffold(
backgroundColor: Colors.blue,
drawer: DrawerPage(),
key: scaffoldKey,
body: NestedScrollView(
headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
return <Widget>[
SliverAppBar(
expandedHeight: 0,
pinned: false,
floating: true,
forceElevated: innerBoxIsScrolled,
backgroundColor: Colors.green,
leading: GestureDetector(
onTap: () => scaffoldKey.currentState?.openDrawer(),
child: const DrawerIcon()),
title: const Center(
child: Text(app_name),
),
actions: [
//Icon(Icons.search),
(_currentTab == TabItem.events)
? Icon(Icons.filter)
: Container(),
],
),
];
},
body: Builder(builder: (BuildContext context) {
if (_currentTab == TabItem.events) {
return CustomScrollView(
key: const PageStorageKey<TabItem>(TabItem.events),
slivers: [
SliverList(
delegate: SliverChildListDelegate([
for (var index = 1; index < 1000; index++)
Text(
index.toString(),
textAlign: TextAlign.center,
style: const TextStyle(
color: Colors.white,
fontWeight: FontWeight.w600,
fontSize: 40.0,
letterSpacing: 2.0,
wordSpacing: 100.0,
),
),
])),
],
);
} else if (_currentTab == TabItem.messages) {
return const Center(
child: Text('message list'),
);
} else if (_currentTab == TabItem.notifications) {
return const Center(
child: Text('notitifcatiion list'),
);
}
return Text('notitifcatiion list');
}),
),
bottomNavigationBar: BottomNavigation(
currentTab: _currentTab,
onSelectTab: _selectTab,
),
);
}
}
tab_item.dart
import 'package:flutter/material.dart';
enum TabItem { events, messages, notifications }
const Map<TabItem, String> tabName = {
TabItem.events: 'events',
TabItem.messages: 'messages',
TabItem.notifications: 'notifications',
};
botom_navigation.dart
import 'package:flutter/material.dart';
import 'package:liveitup/app/screens/HomeScreen/tabs/tab_item.dart';
class BottomNavigation extends StatelessWidget {
BottomNavigation({required this.currentTab, required this.onSelectTab});
final TabItem currentTab;
final ValueChanged<TabItem> onSelectTab;
#override
Widget build(BuildContext context) {
return BottomNavigationBar(
type: BottomNavigationBarType.fixed,
items: [
BottomNavigationBarItem(
icon: Icon(
Icons.home,
color: currentTab == TabItem.events ? Colors.black : Colors.grey,
),
label: tabName[TabItem.events],
),
BottomNavigationBarItem(
icon: Icon(
Icons.message,
color: currentTab == TabItem.messages ? Colors.black : Colors.grey,
),
label: tabName[TabItem.messages],
),
BottomNavigationBarItem(
icon: Icon(
Icons.notifications,
color: currentTab == TabItem.notifications
? Colors.black
: Colors.grey,
),
label: tabName[TabItem.notifications],
),
],
onTap: (index) => onSelectTab(
TabItem.values[index],
),
currentIndex: currentTab.index,
//selectedItemColor: Colors.black,
);
}
}

Why there is no index in navigation bar item?

This is the code without error messages:
import 'dart:ui';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
class MyStatefulWidget extends StatefulWidget {
const MyStatefulWidget({Key? key}) : super(key: key);
#override
State<MyStatefulWidget> createState() => BottomNavigation();
}
/// This is the private State class that goes with MyStatefulWidget.
class BottomNavigation extends State<MyStatefulWidget> {
int _selectedIndex = 0;
List<Widget> _widgetOptions= <Widget>[
Text('Home'),
Text('Message')
];
static const TextStyle optionStyle =
TextStyle(fontSize: 30, fontWeight: FontWeight.bold);
void _onItemTapped(int index) {
setState(() {
_selectedIndex=index;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
actions: <Widget>[
IconButton(icon: Icon(Icons.search), onPressed: () {}),
],
),
body: Container(
decoration: BoxDecoration(
image: DecorationImage(
image:
AssetImage("assets/OptimizeYourFood/OptimizeYourFood2.png"),
fit: BoxFit.cover,
),
color: Colors.transparent)
),
bottomNavigationBar: BottomNavigationBar(
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(Icons.local_dining),
label: 'Reduce',
),
BottomNavigationBarItem(
icon: Icon(FontAwesomeIcons.recycle),
label: 'Reuse and recycle',
),
],
currentIndex: _selectedIndex,
selectedItemColor: Colors.amber[800],
onTap: _onItemTapped,
),
);
}
}
[Nothing comes out of bottom navigation bar items][1]
..................................................................................................................................................................................................This is the end. This is the end. This is the end. This is the end. This is the end.
New Code
New Picture
You are changing the index but not the UI. use _widgetOptions on body. You can directly use body:_widgetOptions[_selectedIndex ] .
class MyStatefulWidget extends StatefulWidget {
const MyStatefulWidget({Key? key}) : super(key: key);
#override
State<MyStatefulWidget> createState() => BottomNavigation();
}
/// This is the private State class that goes with MyStatefulWidget.
class BottomNavigation extends State<MyStatefulWidget> {
int _selectedIndex = 0;
List<Widget> _widgetOptions = <Widget>[Text('Home'), Text('Message')];
static const TextStyle optionStyle =
TextStyle(fontSize: 30, fontWeight: FontWeight.bold);
void _onItemTapped(int index) {
print("tapped $index");
setState(() {
_selectedIndex = index;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
actions: <Widget>[
IconButton(icon: Icon(Icons.search), onPressed: () {}),
],
),
body: Column(
children: [
_widgetOptions[_selectedIndex]
// Container(
// decoration: BoxDecoration(
// image: DecorationImage(
// image:
// AssetImage("assets/OptimizeYourFood/OptimizeYourFood2.png"),
// fit: BoxFit.cover,
// ),
// color: Colors.transparent)),
],
),
bottomNavigationBar: BottomNavigationBar(
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(Icons.local_dining),
label: 'Reduce',
),
BottomNavigationBarItem(
icon: Icon(Icons.ac_unit),
// Icon(FontAwesomeIcons.recycle),
label: 'Reuse and recycle',
),
],
currentIndex: _selectedIndex,
selectedItemColor: Colors.amber[800],
onTap: _onItemTapped,
),
);
}
}
It will use the items array index.
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem( // <- index 0
icon: Icon(Icons.local_dining),
label: 'Reduce',
),
BottomNavigationBarItem( // <- index 1
icon: Icon(FontAwesomeIcons.recycle),
label: 'Reuse and recycle',
),
...
],

Change tab on BottomNavigationBar Flutter programmatically and without using onTap of BottomNavigationBar?

I am working on a flutter application where I need to redirect to the first screen on BottomNavigationBar when the user presses back from any other screen of the remaining BottomNavigationBar screens. For now, I have added redirecting event on a simple button, will replace this on _onWillPop event.
Please find the code below:
class HomeScreen extends StatefulWidget {
#override
_HomeScreenState createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
final PageStorageBucket bucket = PageStorageBucket();
Widget currentScreen = HomeFragment();
int currentTab = 0;
static int selectedIndexN = 0;
static const TextStyle optionStyle = TextStyle(fontSize: 30, fontWeight: FontWeight.bold);
List<Widget> _widgetOptions1 = <Widget>[
HomeFragment(),
LoginFargment(),
SignUpFargment(),
ProfileFargment(),
];
void changeTabMethod(int index) {
print('changeTabMethod is called');
setState(() {
selectedIndexN = index;
});
print('changeTabMethod is called : selectedIndexN : $selectedIndexN');
}
#override
Widget build(BuildContext context) {
return Scaffold(
// return GetBuilder<DashboardController>(
body: Center(
child: _widgetOptions1.elementAt(selectedIndexN),
),
bottomNavigationBar: BottomNavigationBar(
type: BottomNavigationBarType.fixed,
currentIndex: selectedIndexN,
onTap: changeTabMethod,
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(Icons.home),
label: 'Home',
),
BottomNavigationBarItem(
icon: Icon(Icons.business),
label: 'Login',
),
BottomNavigationBarItem(
icon: Icon(Icons.school),
label: 'SignUp',
),
BottomNavigationBarItem(
icon: Icon(Icons.school),
label: 'Profile',
),
],
),
);
}
}
Profile screen code:
class ProfileFargment extends StatefulWidget {
#override
_ProfileFragmentState createState() => _ProfileFragmentState();
}
class _ProfileFragmentState extends State<ProfileFargment> {
#override
Widget build(BuildContext context) {
return Scaffold(
body:SafeArea(
child: Container(
padding: EdgeInsets.all(20.0),
height: double.infinity,
width: double.infinity,
color: Colors.teal,
child: GestureDetector(
onTap: () {
//Calling method changeTabMethod(0)
HomeScreen().createState().changeTabMethod(0);
},
child: Container(
margin: EdgeInsets.only(top: 20.0),
height: 40.0,
width: 150.0,
color: Colors.white,
child: Center(child: Text('Profile'),),
),
),
),
),
);
}
}
On the other hand, when I call changeTabMethod from a ProfileFragment screen, it will enter into changeTabMethod but couldn't execute the setState method. So my tab is not changing.
You can consider this console report:
changeTabMethod is called is only printed the second print after setState was not executed.
Can you please let me know what or where I am doing anything wrong?
Thanks in advance :-)
Try below code. By passing function as parameter you can trigger function on home page from any other page.
Home screen code:
class HomeScreen extends StatefulWidget {
#override
_HomeScreenState createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
final PageStorageBucket bucket = PageStorageBucket();
// Widget currentScreen = HomeFragment();
int currentTab = 0;
static int selectedIndexN = 0;
static const TextStyle optionStyle =
TextStyle(fontSize: 30, fontWeight: FontWeight.bold);
Widget _widgetOptions1(int index) {
switch (index) {
case 0:
return ProfileFargment(onButtonPressed: changeTabMethod);
case 1:
return Container(child: Text("Page - 2 "));
case 2:
return Container(child: Text("Page - 3 "));
default:
return Container();
}
}
void changeTabMethod(int index) {
print('changeTabMethod is called');
setState(() {
selectedIndexN = index;
});
print('changeTabMethod is called : selectedIndexN : $selectedIndexN');
}
#override
Widget build(BuildContext context) {
return Scaffold(
// return GetBuilder<DashboardController>(
body: Center(
child: _widgetOptions1(selectedIndexN),
),
bottomNavigationBar: BottomNavigationBar(
type: BottomNavigationBarType.fixed,
currentIndex: selectedIndexN,
onTap: changeTabMethod,
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(Icons.home),
label: 'Home',
),
BottomNavigationBarItem(
icon: Icon(Icons.business),
label: 'Login',
),
BottomNavigationBarItem(
icon: Icon(Icons.school),
label: 'SignUp',
),
BottomNavigationBarItem(
icon: Icon(Icons.school),
label: 'Profile',
),
],
),
);
}
}
Profile screen code:
class ProfileFargment extends StatefulWidget {
final void Function(int) onButtonPressed;
const ProfileFargment({Key key, this.onButtonPressed});
#override
_ProfileFragmentState createState() => _ProfileFragmentState();
}
class _ProfileFragmentState extends State<ProfileFargment> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Container(
padding: EdgeInsets.all(20.0),
height: double.infinity,
width: double.infinity,
color: Colors.teal,
child: GestureDetector(
onTap: () {
//Calling method changeTabMethod(0)
// HomeScreen().createState().changeTabMethod(0);
widget.onButtonPressed(0);
},
child: Container(
margin: EdgeInsets.only(top: 20.0),
height: 40.0,
width: 150.0,
color: Colors.white,
child: Center(
child: Text('Profile'),
),
),
),
),
),
);
}
}
This is actually quite simple, you just need to pass the function off to the child widget.
So your ProfileFragment will take a variable called changeTab of type Function(int):
Function(int) changeTab;
ProfileFragment(this.changeType); // Constructor
You pass that off when you create the widget inside the _HomeScreenState:
List<Widget> _widgetOptions1 = <Widget>[
…
ProfileFargment(changeTabMethod),
];
Then you can call the function directly in the _ProfileFragmentState:
onTap: () => widget.changeTab(0);

How to create a button navigation bar with a stateless widget in flutter?

import 'package:flutter/material.dart';
import 'auth.dart';
// Log Out Button
class HomePage extends StatelessWidget {
HomePage({this.auth, this.onSignedOut});
final BaseAuth auth;
final VoidCallback onSignedOut;
void _signedOut() async {
try {
await auth.signOut();
onSignedOut();
} catch (e) {
print(e);
}
}
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text('Home'),
actions: <Widget>[
new FlatButton(
child: new Text('Logout',
style: new TextStyle(fontSize: 17.0, color: Colors.lime)),
onPressed: _signedOut)
],
),
);
}
}
Want to add a navigation bar however to be able to change the state (moving from one page to another) it needs to be in a statefulwidget. How do I get around this?<
It has to be a StatefulWidget
Hope this helps
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
class BottomNavigationBar1 extends StatefulWidget{
#override
_BottomNavigationBar1State createState() =>_BottomNavigationBar1State();
}
class _BottomNavigationBar1State extends State<BottomNavigationBar1>{
int _currentIndex =0;
static const TextStyle optionStyle = TextStyle(fontSize: 30, fontWeight: FontWeight.bold);
static const List<Widget> _widgetOptions = <Widget>[
Text(
'Index 0: Home',
style: optionStyle,
),
Text(
'Index 1: Business',
style: optionStyle,
),
Text(
'Index 2: School',
style: optionStyle,
),
];
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("BottomNavigationBar Sample"),
),
body: Center(
child: _widgetOptions.elementAt(_currentIndex),
),
bottomNavigationBar: BottomNavigationBar(
items: [
BottomNavigationBarItem(
icon: Icon(Icons.home),
title: Text('Home')
),
BottomNavigationBarItem(
icon: Icon(Icons.business),
title: Text('Business'),
),
BottomNavigationBarItem(
icon: Icon(Icons.school),
title: Text('School'),
),
],
currentIndex: _currentIndex,
onTap: (index){
setState(() {
_currentIndex = index;
});
},
selectedItemColor: Colors.amber,
),
);
}
}