Flutter bottom Navigation bar with Routes - flutter

I want to navigate through pages using routes and Navigator.pushNamed() on a Bottom Navigation Bar. Here, I'm using a FlashyTab bar for aesthetics. To be more specific, pressing each of the icons on the navigation bar should take me to a different page, and I want to implement this using routes.
#override
Widget build(BuildContext context) {
Size size = MediaQuery.of(context).size;
return Scaffold(
bottomNavigationBar: FlashyTabBar(
animationCurve: Curves.linear,
selectedIndex: _selectedIndex,
showElevation: true,
onItemSelected: (index) => setState(() {
_selectedIndex = index;
}),
items: [
FlashyTabBarItem(
icon: const Icon(Icons.account_box),
title: const Text('Challenger'),
),
FlashyTabBarItem(
icon: const Icon(Icons.phone),
title: const Text('Contact'),
),
FlashyTabBarItem(
icon: const Icon(Icons.dashboard_rounded),
title: const Text('Events'),
),
FlashyTabBarItem(
icon: const Icon(Icons.badge),
title: const Text('Quick Scan'),
),
],
),
body:
);
}

In your screen define this
List<Widget> pageList = [
const ChallengerScreen(),
const ContactScreen(),
const EventsScreen(),
const QuickScanScreen(),
];
In body use it like this
return Scaffold(
bottomNavigationBar: FlashyTabBar(
animationCurve: Curves.linear,
selectedIndex: _selectedIndex,
showElevation: true,
onItemSelected: (index) => setState(() {
_selectedIndex = index;
}),
items: [
FlashyTabBarItem(
icon: const Icon(Icons.account_box),
title: const Text('Challenger'),
),
FlashyTabBarItem(
icon: const Icon(Icons.phone),
title: const Text('Contact'),
),
FlashyTabBarItem(
icon: const Icon(Icons.dashboard_rounded),
title: const Text('Events'),
),
FlashyTabBarItem(
icon: const Icon(Icons.badge),
title: const Text('Quick Scan'),
),
],
),
//you have to just do changes here...
body:pageList.elementAt(_selectedIndex)
);
You don't need to use Navigator.pushNamed() it not the right method to do.

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(

How do I set the bottom navigation bar for a Flutter app page by page?

I would like to set whether to show the bottom navigation bar in a Flutter app page/screen/route by route. For example, when the user navigates through their files and clicks on folders, I want to show the bottom navigation bar. But when the user clicks on a "Create" button, I would not like the bottom navigation for the rest of this flow, and the user navigates backward through the back button in the app bar.
If this is not possible without a very customized, hacky, inflexible, complication solution, I would also be fine with choosing at the beginning of the flow whether to remove the bottom navigation bar.
I have tried the "normal" method, in which the bottom navigation bar only stays for the buttons that are in the bar itself, and it does not persist for anything else (using an IndexedStack and a _currentIndex variable). I have also tried the opposite, in which the bottom navigation shows for everything, which is also not desirable.
Here's what I have currently:
MyApp top-level widget:
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flytrap Audio',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const CurrentPage(),
);
}
CurrentPageState (stateful) Widget
Widget build(BuildContext context) {
return Scaffold(
body: IndexedStack(
index: _currentIndex,
children: screens,
),
bottomNavigationBar: BottomNavigationBar(
type: BottomNavigationBarType.fixed,
showUnselectedLabels: false,
currentIndex: _currentIndex,
onTap: (index) {
// debugPrint("index: $index");
setState(() => _currentIndex = index);
// _navigatorKey.currentState!
// .pushNamedAndRemoveUntil(screens[index], (route) => false);
// debugPrint("Navigated to ${screens[index]}");
},
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(Icons.folder),
label: 'Files',
),
BottomNavigationBarItem(
icon: Icon(Icons.live_tv),
label: 'Live Broadcasts',
),
BottomNavigationBarItem(
icon: Icon(Icons.settings),
label: 'Settings',
),
],
),
);
}
And each page, like FolderPage is a Scaffold
I think you can check my code, I do the little same as you said.But I use the PageView instead:
final _listPage = [
const Page1(),
const Page2(),
const Page3(),
const Page4()
];
final _controller = PageController();
int _indexSelected = 0;
void _onSelected(int index) {
setState(() {
_indexSelected = index;
});
}
Widget build(BuildContext context) {
return Scaffold(
body: PageView(
controller: _controller,
onPageChanged: _onSelected,
children: _listPage,
),
bottomNavigationBar: BottomNavigationBar(
items: const [
BottomNavigationBarItem(
icon: ImageIcon(
AssetImage('assets/images/bottom_tab/bw_u.png'),
size: 25,
),
label: 'Item 0'),
BottomNavigationBarItem(
icon: Icon(Icons.shopping_bag), label: 'Item 1'),
BottomNavigationBarItem(
icon: Icon(Icons.account_circle_outlined), label: 'Item 2'),
BottomNavigationBarItem(icon: Icon(Icons.widgets), label: 'Item 3')
],
currentIndex: _indexSelected,
onTap: (index) => _controller.animateToPage(index,
duration: const Duration(milliseconds: 200), curve: Curves.easeIn),
selectedItemColor: const Color.fromARGB(255, 38, 112, 205),
unselectedItemColor: Colors.grey,
type: BottomNavigationBarType.fixed,
),
);
}

how to access PageViewController outside of widget

TabScreen is my main widget in my app that includes a BottomNavigationBar and a PageView to transition between pages.
PageController allows me to change views and everything is fine here, but there is one thing missing. How can I change my PageView controller outside of TabScreen? I'd like to put a button to access my main PageView controller from within my pages.
class _TabsScreenState extends State<TabsScreen> {
bool _isloading = true;
int? _selectedIndex;
List<Widget>? _pages = [
HomeScreen(),
CurrenPlanDetail(),
Container(),
ProfileScreen(),
SettingScreens(),
];
PageController? _pageController;
#override
void initState() {
_selectedIndex = 0;
_pageController = PageController(initialPage: _selectedIndex!);
}
}
Widget build(BuildContext context) {
return Scaffold(
body: PageView(
controller: _pageController,
children: _pages!,
physics: NeverScrollableScrollPhysics(),
),
bottomNavigationBar: Visibility(
visible: !_isloading,
child: BottomNavigationBar(
type: BottomNavigationBarType.fixed,
selectedItemColor: kNewPurple,
//unselectedItemColor: Colors.grey,
currentIndex: _selectedIndex!,
onTap: (value) {
setState(() {
_selectedIndex = value;
_pageController!.jumpToPage(_selectedIndex!);
});
},
backgroundColor: Colors.grey[300],
items: [
BottomNavigationBarItem(
icon: Icon(
Ionicons.home_outline,
size: 15.sp,
),
label: 'Home'),
BottomNavigationBarItem(
icon: Icon(
Ionicons.reader_outline,
size: 15.sp,
),
label: 'Plan'),
BottomNavigationBarItem(
icon: ElevatedButton(
style: ElevatedButton.styleFrom(
shape: CircleBorder(),
fixedSize: Size(50, 50),
),
onPressed: () {
showModalBottomSheet(
context: context,
builder: (context) {
return FloatingButton();
});
},
child: Icon(Ionicons.add)),
label: ''),
BottomNavigationBarItem(
icon: Icon(
Ionicons.happy_outline,
size: 15.sp,
),
label: 'Profile'),
BottomNavigationBarItem(
icon: Icon(
Ionicons.settings_outline,
size: 15.sp,
),
label: 'Setting'),
],
),
),
);
}
}
for example, somewhere in my app, I'd like to put a button and pass a function like this :
_pageController!.jumpToPage(1);
Define PageController as static and
TabScreen.pageController.jumpToPage(1);

How to toggle visibility of TabBar with Bottom Navigation Items in Flutter

I have a bottomNavigationBar and an AppBar in my flutter app. At the bottom of the AppBar is a TabBar consisting of two items. So I want the TabBar to be invisible when some items of the BottomNavigationBar is clicked. I tried to assign the Visibility class to my TabBar with a Boolean variable but it doesn't work. It seems like I can't handle the TabBar widget separately.
How do resolve this?
class DashBoardPage extends StatefulWidget {
#override
_DashBoardPageState createState() => _DashBoardPageState();
}
class _DashBoardPageState extends State<DashBoardPage> {
SharedPreferences sharedPreferences;
bool showTabs = false;
int tabsIndex = 0;
int _currentIndex = 0;
String _appBarText = "Welcome, User";
Widget callPage(int currentIndex) {
switch (currentIndex) {
case 0:
showTabs = true;
_appBarText = "Welcome, User";
return TabBarView(
children:[
new HomePage(),
new SchedulePage()
]
);
break;
case 1:
showTabs = false;
break;
case 2:
showTabs = false;
break;
default:
return HomePage();
}
}
#override
void initState() {
super.initState();
checkLoginState();
}
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'MAF Mentor',
debugShowCheckedModeBanner: false,
home: DefaultTabController(
length: choices.length,
child: Scaffold(
appBar: AppBar(
backgroundColor: Color(0xFFFFFFFF),
title: Text(
_appBarText,
style: TextStyle(
color: Color(0xFF1C2447),
fontFamily: 'Muli',
fontSize: 16.0,
),
),
bottom: showTabs? TabBar(
isScrollable: true,
tabs: choices.map<Widget>((Choice choice) {
return Tab(
text: choice.title,
icon: Icon(choice.icon),
);
}).toList(),
labelColor: Color(0xFF1C2447),
):null,
actions: <Widget>[
IconButton(
icon: Icon(
Icons.account_circle,
color: Color(0xFF1C2447),
),
onPressed: () {
Navigator.of(context).pushNamed('/profile_page');
},
),
IconButton(
icon: Icon(
Icons.notifications,
color: Color(0xFF1C2447),
),
onPressed: () {
// do something
},
),
],
), //AppBar
body: callPage(_currentIndex),
bottomNavigationBar: BottomNavigationBar(
showSelectedLabels: false,
showUnselectedLabels: false,
fixedColor: Color(0xFF1C2447),
currentIndex: _currentIndex,
onTap: (value) {
_currentIndex = value;
callPage(_currentIndex);
setState(() {
});
},
items: [
BottomNavigationBarItem(
icon: Icon(Icons.home), title: Text("Bar 1")),
BottomNavigationBarItem(
icon: Icon(Icons.people), title: Text("Bar 2")),
BottomNavigationBarItem(
icon: Icon(Icons.history), title: Text("Bar 3"))
],
),
),
),
);
}
bottom requires a PreferredSizeWidget so you can not use the Visibility widget there. You can use a boolean variable to do that. You can see the whole code below. Since I don't know your choices and tabs I randomly put something. But the idea is if you want to show TabBar when user tap BottomNavigationBarItem
number 1 you just update your boolean variable as true. Otherwise make it false.
class TabBarExample extends StatefulWidget {
#override
_TabBarExampleState createState() => _TabBarExampleState();
}
class _TabBarExampleState extends State<TabBarExample> {
bool showTabs = false;
int selectedIndex = 0;
#override
Widget build(BuildContext context) {
return DefaultTabController(
length: 2,
child: Scaffold(
appBar: AppBar(
backgroundColor: Color(0xFFFFFFFF),
title: Text(
'_appBarText',
style: TextStyle(
color: Color(0xFF1C2447),
fontFamily: 'Muli',
fontSize: 16.0,
),
),
bottom: showTabs
? TabBar(
isScrollable: true,
tabs: <Widget>[
Tab(
text: 'Choice1',
icon: Icon(Icons.add_circle_outline),
),
Tab(
text: 'Choice1',
icon: Icon(Icons.add_circle),
),
],
labelColor: Color(0xFF1C2447),
)
: null,
),
bottomNavigationBar: BottomNavigationBar(
currentIndex: selectedIndex,
items: [
BottomNavigationBarItem(
icon: Icon(Icons.home), title: Text('first')),
BottomNavigationBarItem(
icon: Icon(Icons.favorite), title: Text('second')),
],
onTap: (index) {
if (index == 1) {
setState(() => showTabs = true);
} else {
setState(() => showTabs = false);
}
setState(() => selectedIndex = index);
},
),
),
);
}
}

Hide the bottom navigation bar when clicking on one bottom navigation bar item (and loading related page) - Flutter

I have a bottom navigation bar defined separately in a file, containing 5 items, and loading 5 pages (which doesn't have defined a bottom navigation bar). It should be present on 4 of the loaded pages but should disappear on the 5th page (CHAT). All the solutions I found online refers to hiding the bar while scrolling up or down, I think I'm quite close to the expected result but I didn't sort it out yet... The code for that "controller" that generates the B-N-Bar is below, a screenshot with the bottom as well. Thank you.
class BottomNavigationBarController extends StatefulWidget {
#override
_BottomNavigationBarControllerState createState() =>
_BottomNavigationBarControllerState();
}
class _BottomNavigationBarControllerState
extends State<BottomNavigationBarController> {
final List<Widget> pages = [
MyHome(
key: PageStorageKey('Page1'),
),
MyStats(
key: PageStorageKey('Page2'),
),
MyCategories(
key: PageStorageKey('Page3'),
),
MyPeopleList(
key: PageStorageKey('Page4'),
),
MyChat(
key: PageStorageKey('Page5'),
),
];
final PageStorageBucket bucket = PageStorageBucket();
int _selectedIndex = 0;
Widget _bottomNavigationBar(int selectedIndex) => BottomNavigationBar(
onTap: (int index) => setState(() => _selectedIndex = index),
currentIndex: selectedIndex,
type: BottomNavigationBarType.fixed,
//
iconSize: 24,
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(Icons.home),
title: Text(
'HOME',
),
),
BottomNavigationBarItem(
icon: Icon(Icons.insert_chart),
title: Text(
'STATS',
),
),
BottomNavigationBarItem(
icon: Icon(Icons.view_list),
title: Text(
'INVENTORY',
),
),
BottomNavigationBarItem(
icon: Icon(Icons.group),
title: Text(
'PEOPLE',
),
),
BottomNavigationBarItem(
icon: Icon(Icons.forum),
title: Text(
'CHAT',
),
),
],
);
#override
Widget build(BuildContext context) {
return Scaffold(
bottomNavigationBar: _bottomNavigationBar(_selectedIndex),
body: PageStorage(
child: pages[_selectedIndex],
bucket: bucket,
),
);
}
}
I did it with an IF/Else in the bottom:
#override
Widget build(BuildContext context) {
if (_selectedIndex < 4) {
return Scaffold(
bottomNavigationBar: _bottomNavigationBar(_selectedIndex),
body: PageStorage(
child: pages[_selectedIndex],
bucket: bucket,
),
);
} else {
return Scaffold(
body: PageStorage(
child: pages[_selectedIndex],
bucket: bucket,
),
);
}
}