Issue
I am implementing Curved_Navigation_Bar in my Flutter poject and I am not using any class(i.e. Stateful / Stateless). I want to change the state of the icons that are in my curved_navigation_bar, means I want that animation effect on my navigation bar. Because the respective pages of those icons are navigating but not those items. No matter on which icon I click, it is still showing that first icon only. The animation/interpolation of icons is not happening.
As I am not using any Stateful/Stateless class, so I am not using Scaffold. Inside Scaffold we can change the state of the current object using setState(() { }).
So how can I change the state of my navigation bar?
Here is my code below:
navigation_bar.dart
import 'package:flutter/material.dart';
import 'package:curved_navigation_bar/curved_navigation_bar.dart';
import 'package:thehelpdesk/components/home/history.dart';
import 'package:thehelpdesk/components/home/home.dart';
import 'package:thehelpdesk/components/home/menu.dart';
import 'package:thehelpdesk/components/home/notification.dart';
import 'package:thehelpdesk/components/home/person.dart';
int currentIndex = 0 ;
Widget navBarSection(Color color, Color btnColor, BuildContext context) {
return CurvedNavigationBar(
index: 0,
items:
[
Icon(Icons.home, color: Colors.white),
Icon(Icons.notifications, color: Colors.white),
Icon(Icons.menu, color: Colors.white),
Icon(Icons.history, color: Colors.white),
Icon(Icons.person, color: Colors.white),
],
color: color,
buttonBackgroundColor: btnColor,
animationCurve: Curves.easeInCubic,
animationDuration: Duration(milliseconds: 600),
onTap: (index) {
if(currentIndex == 0){
Navigator.of(context).push(MaterialPageRoute(builder: (context) => HomePage()));
currentIndex = index ;
}
if(currentIndex == 1){
Navigator.of(context).push(MaterialPageRoute(builder: (context) => NotificationPage()));
currentIndex = index ;
}
if(currentIndex == 2){
Navigator.of(context).push(MaterialPageRoute(builder: (context) => MenuPage()));
currentIndex = index ;
}
if(currentIndex == 3){
Navigator.of(context).push(MaterialPageRoute(builder: (context) => HistoryPage()));
currentIndex = index ;
}
if(currentIndex == 4){
Navigator.of(context).push(MaterialPageRoute(builder: (context) => PersonPage()));
currentIndex = index ;
}
}
);
One of the pages I want to navigate on tapping a icon:
home.dart
import 'package:flutter/material.dart';
import 'package:thehelpdesk/widgets/appbar.dart';
import 'package:thehelpdesk/widgets/navigation_bar.dart';
class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: aapBarSection('Home', Colors.blueAccent[700], context),
bottomNavigationBar: navBarSection(
Colors.blueAccent[700],
Colors.blueAccent[700],
context
),
);
}
}
Another page on tapping the 2nd icon:
notification.dart
import 'package:flutter/material.dart';
import 'package:thehelpdesk/widgets/appbar.dart';
import 'package:thehelpdesk/widgets/navigation_bar.dart';
class NotificationPage extends StatefulWidget {
@override
_NotificationPageState createState() => _NotificationPageState();
}
class _NotificationPageState extends State<NotificationPage> {
final message = [
'Hi Xyz,your invoice for It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged.',
'Hi Xyz, Agility Rehab Care wishing you a very happy birthday! for It has survived not only five centuries, but also the leap remaining essentially unchanged.',
'Hi Xyz, From our Agility Rehab Care you are being reminded that you have an appointment with us on this Friday.',
'Hi Xyz, This is a reminder for you from Agility Rehab Care It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout.',
];
final images = [
'assets/images/Invoice.png',
'assets/images/cake.png',
'assets/images/calender.png',
'assets/images/Reminder.png'
];
String date = '22/02/2021';
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: aapBarSection('Notification',Colors.blueAccent[700],context),
bottomNavigationBar: navBarSection(
Colors.blueAccent[700],
Colors.blueAccent[700],
context
),
body: ListView.builder(
itemCount: message.length,
itemBuilder: (context, index) {
return Padding(
padding: const EdgeInsets.fromLTRB(10, 10, 10, 10),
child: SizedBox(
height: 200,
child: Card(
elevation: 5.0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
),
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
child: Column(
children: [
Flexible(
flex: 7,
child: Container(
child: Row(
children: [
Expanded(
flex: 2,
child: Container(
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage(
images[index]))),
),
),
Expanded(
flex: 8,
child: Container(
child: Text(message[index]),
),
),
],
),
),
),
Flexible(
flex: 3,
child: Padding(
padding: const EdgeInsets.fromLTRB(10, 10, 10, 10),
child: Container(
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [Text(date)],
),
),
),
),
],
),
),
)),
),
);
})
);
}
}
Solution
The short answer is that just add currentIndex
as one of the parameter inside your navBarSection
.
navigation_bar.dart
Widget navBarSection(
int currentIndex,
Color color,
Color btnColor,
BuildContext context,
) {
return CurvedNavigationBar(
index: currentIndex,
items: [
Icon(Icons.home, color: Colors.white),
Icon(Icons.notifications, color: Colors.white),
Icon(Icons.menu, color: Colors.white),
Icon(Icons.history, color: Colors.white),
Icon(Icons.person, color: Colors.white),
],
color: color,
buttonBackgroundColor: btnColor,
animationCurve: Curves.easeInCubic,
animationDuration: Duration(milliseconds: 600),
onTap: (index) {
if (currentIndex == 0) {
Navigator.of(context)
.push(MaterialPageRoute(builder: (context) => HomePage()));
currentIndex = index;
}
if (currentIndex == 1) {
Navigator.of(context).push(
MaterialPageRoute(builder: (context) => NotificationPage()));
currentIndex = index;
}
if (currentIndex == 2) {
Navigator.of(context)
.push(MaterialPageRoute(builder: (context) => MenuPage()));
currentIndex = index;
}
if (currentIndex == 3) {
Navigator.of(context)
.push(MaterialPageRoute(builder: (context) => HistoryPage()));
currentIndex = index;
}
if (currentIndex == 4) {
Navigator.of(context)
.push(MaterialPageRoute(builder: (context) => PersonPage()));
currentIndex = index;
}
});
}
Inside home.dart
, just pass the currentIndex
of the page.
home.dart
class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: aapBarSection('Home', Colors.blueAccent[700], context),
bottomNavigationBar: navBarSection(
0,
Colors.blueAccent[700],
Colors.blueAccent[700],
context,
),
);
}
}
This should solve your problem but as you can see, this is not the best way to implement the bottomnavigationbar
and widget due to:
- You will lose the animation that the package provided.
- It does not comply with the bottom navigation behavior since it will navigate to a new page instead of replacing it.
To solve this, create a new stateful widget,as for this example, I called it main_page.dart
.
main_page.dart
class MainPage extends StatefulWidget {
@override
_MainPageState createState() => _MainPageState();
}
class _MainPageState extends State<MainPage> {
int _currentIndex = 0;
List<Widget> _pages = [
HomePage(),
NotificationPage(),
MenuPage(),
HistoryPage(),
PersonPage(),
];
@override
Widget build(BuildContext context) {
return Scaffold(
body: _pages.elementAt(_currentIndex),
bottomNavigationBar: CurvedNavigationBar(
backgroundColor: Colors.blueAccent,
items: [
Icon(Icons.home, color: Colors.white),
Icon(Icons.notifications, color: Colors.white),
Icon(Icons.menu, color: Colors.white),
Icon(Icons.history, color: Colors.white),
Icon(Icons.person, color: Colors.white),
],
color: Colors.blueAccent[700],
buttonBackgroundColor: Colors.blueAccent[700],
animationCurve: Curves.easeInCubic,
animationDuration: Duration(milliseconds: 600),
onTap: (index) {
setState(() {
_currentIndex = index;
});
},
),
);
}
}
Called the the main_page.dart
inside your main.dart
.
main.dart
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MainPage(),
);
}
}
lastly, remove any bottomNavigationBar
from home,history,menu,notification,and person page.
The result is
Answered By – Hafiz Mokhtar
Answer Checked By – Pedro (FlutterFixes Volunteer)