Flutter - codes not working correctly after putting inside setState - flutter

I am trying to add to an array list after user clicked. I am using InkWell, onTap function.
child: InkWell(
onTap: () {
if (tempArray.contains(entries[index].toString())) {
tempArray.remove(entries[index].toString());
print(tempArray.toList().toString());
} else {
tempArray.add(entries[index].toString());
print(tempArray.toList().toString());
}
My debug console is printing these out,
enter image description here
However, when i put the codes inside a setState, this is what got printed
child: InkWell(
onTap: () {
setState(() {
if (tempArray.contains(entries[index].toString())) {
tempArray.remove(entries[index].toString());
print(tempArray.toList().toString());
} else {
tempArray.add(entries[index].toString());
print(tempArray.toList().toString());
}
});
enter image description here
What i am trying to do, is to show/hide the 'trailing' icon in the ListTile, based on whatever user had selected the particular item.
My full codes (without the setState) are as follows,
import 'package:flutter/material.dart';
class Personal1Redo extends StatefulWidget {
#override
_Personal1RedoState createState() => _Personal1RedoState();
}
class _Personal1RedoState extends State<Personal1Redo> {
#override
Widget build(BuildContext context) {
final mediaQuery = MediaQuery.of(context);
List<String> entries = [
'Residental Loan',
'Personal Loan',
'Car Loan',
'Renovation Loan',
'Savings Account',
];
List<String> tempArray = [];
final heading = Column(
children: [
const SizedBox(
height: 40,
),
SizedBox(
height: (mediaQuery.size.height - mediaQuery.padding.top) * 0.1,
child: const Align(
alignment: Alignment.center,
child: Text(
'What do you aspire to do?',
textAlign: TextAlign.center,
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 20,
),
),
),
),
const SizedBox(
height: 20,
),
],
);
return Scaffold(
appBar: AppBar(
title: Text('Borrower redo'),
),
body: SingleChildScrollView(
child: Column(
children: <Widget>[
heading,
ListView.builder(
shrinkWrap: true,
itemCount: entries.length,
itemBuilder: (ctx, index) {
return Container(
width: mediaQuery.size.width * 0.9,
padding: const EdgeInsets.all(15),
child: InkWell(
onTap: () {
if (tempArray.contains(entries[index].toString())) {
tempArray.remove(entries[index].toString());
print(tempArray.toList().toString());
} else {
tempArray.add(entries[index].toString());
print(tempArray.toList().toString());
}
},
child: Card(
margin: const EdgeInsets.all(10),
elevation: 8,
child: ListTile(
title: Text(
entries[index],
style: TextStyle(
color: Colors.grey.shade800,
fontSize: 20,
),
textAlign: TextAlign.center,
),
trailing: tempArray.contains(entries[index])
? Icon(Icons.check_box_outline_blank_outlined)
: null,
),
),
),
);
})
],
),
),
);
}
}
Any helps and guidance is very much appreciated, thanks!!

Define variables and functions outside build method.
As setState method, calls build, every time it is called.
Like this :
import 'package:flutter/material.dart';
class Personal1Redo extends StatefulWidget {
#override
_Personal1RedoState createState() => _Personal1RedoState();
}
class _Personal1RedoState extends State<Personal1Redo> {
List<String> entries = [
'Residental Loan',
'Personal Loan',
'Car Loan',
'Renovation Loan',
'Savings Account',
];
List<String> tempArray = [];
getHeadingWidget(BuildContext context) {
return Column(
children: [
const SizedBox(
height: 40,
),
SizedBox(
height: (mediaQuery!.size.height - mediaQuery.padding.top) * 0.1,
child: const Align(
alignment: Alignment.center,
child: Text(
'What do you aspire to do?',
textAlign: TextAlign.center,
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 20,
),
),
),
),
const SizedBox(
height: 20,
),
],
);
}
#override
Widget build(BuildContext context) {
final mediaQuery = MediaQuery.of(context);
return Scaffold(
appBar: AppBar(
title: Text('Borrower redo'),
),
body: SingleChildScrollView(
child: Column(
children: <Widget>[
getHeadingWidget(context),
ListView.builder(
shrinkWrap: true,
itemCount: entries.length,
itemBuilder: (ctx, index) {
return Container(
width: mediaQuery.size.width * 0.9,
padding: const EdgeInsets.all(15),
child: InkWell(
onTap: () {
if (tempArray.contains(entries[index].toString())) {
tempArray.remove(entries[index].toString());
print(tempArray.toList().toString());
} else {
tempArray.add(entries[index].toString());
print(tempArray.toList().toString());
}
},
child: Card(
margin: const EdgeInsets.all(10),
elevation: 8,
child: ListTile(
title: Text(
entries[index],
style: TextStyle(
color: Colors.grey.shade800,
fontSize: 20,
),
textAlign: TextAlign.center,
),
trailing: tempArray.contains(entries[index])
? Icon(Icons.check_box_outline_blank_outlined)
: null,
),
),
),
);
})
],
),
),
);
}
}

Related

How do i return a container based on a list of item selected in flutter?

I have a list of items
List<String> items = [
"All",
"Jobs",
"Messages",
"Customers",
];
int current = 0;
And this list is directly responsible for my tab bar:
When i tap an item in the Tab bar i want to return a different container on each of them?
How do i go about this in flutter?
I tried returning an if statement just before the container but it seems i don't get the statement correctly.
this is the container i want to return if the item user select is All, and then put conditions in place for the rest items.
this is how i put the condition but it gives me this error
My return statement and code -
current = 0 ??
Container(
margin: const EdgeInsets.only(top: 30),
height: MediaQuery.of(context).size.height * 1,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const SizedBox(
height: 10,
),
Text(
items[current],
style: GoogleFonts.laila(
fontWeight: FontWeight.w500,
fontSize: 30,
color: Colors.deepPurple),
),
],
),
),
current = 1 ?? Text('hello')
FULL WIDGET ADDED
class NotificationsView extends StatefulWidget {
#override
State<NotificationsView> createState() => _NotificationsViewState();
}
class _NotificationsViewState extends State<NotificationsView> {
final controller = Get.put(NotificationsController());
List<String> items = [
"All",
"Jobs",
"Messages",
"Customers",
];
int current = 0;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(
"Notifications".tr,
style: GoogleFonts.poppins(
color: Color(0xff000000),
fontSize: 16,
fontWeight: FontWeight.w600),
),
centerTitle: false,
backgroundColor: Colors.transparent,
elevation: 0,
automaticallyImplyLeading: false,
leadingWidth: 15,
leading: new IconButton(
icon: new Icon(Icons.arrow_back_ios, color: Color(0xff3498DB)),
onPressed: () => {Get.back()},
),
),
body: RefreshIndicator(
onRefresh: () async {
},
child: ListView(
primary: true,
children: <Widget>[
filter(),
],
),
),
);
}
Widget notificationsList() {
return Obx(() {
if (!controller.notifications.isNotEmpty) {
return CircularLoadingWidget(
height: 300,
onCompleteText: "Notification List is Empty".tr,
);
} else {
var _notifications = controller.notifications;
return ListView.separated(
itemCount: _notifications.length,
separatorBuilder: (context, index) {
return SizedBox(height: 7);
},
shrinkWrap: true,
primary: false,
itemBuilder: (context, index) {
var _notification = controller.notifications.elementAt(index);
if (_notification.data['message_id'] != null) {
return MessageNotificationItemWidget(
notification: _notification);
} else if (_notification.data['booking_id'] != null) {
return BookingNotificationItemWidget(
notification: _notification);
} else {
return NotificationItemWidget(
notification: _notification,
onDismissed: (notification) {
controller.removeNotification(notification);
},
onTap: (notification) async {
await controller.markAsReadNotification(notification);
},
);
}
});
}
});
}
Widget filter() {
return Container(
width: double.infinity,
margin: const EdgeInsets.all(5),
child: Column(
children: [
/// CUSTOM TABBAR
SizedBox(
width: double.infinity,
height: 60,
child: ListView.builder(
physics: const BouncingScrollPhysics(),
itemCount: items.length,
scrollDirection: Axis.horizontal,
itemBuilder: (ctx, index) {
return Column(
children: [
GestureDetector(
onTap: () {
setState(() {
current = index;
});
},
child: AnimatedContainer(
duration: const Duration(milliseconds: 300),
margin: const EdgeInsets.all(5),
decoration: BoxDecoration(
color: current == index
? Color(0xff34495E)
: Color(0xffF5F5F5),
borderRadius: BorderRadius.circular(11),
),
child: Center(
child: Padding(
padding: const EdgeInsets.only(
left: 10.0, right: 10.0, top: 5, bottom: 5),
child: Text(
items[index],
style: GoogleFonts.poppins(
fontSize: 12,
fontWeight: FontWeight.w500,
color: current == index
? Colors.white
: Colors.grey),
),
),
),
),
),
],
);
}),
),
/// MAIN BODY
current = 0 ??
Container(
margin: const EdgeInsets.only(top: 30),
height: MediaQuery.of(context).size.height * 1,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const SizedBox(
height: 10,
),
Text(
items[current],
style: GoogleFonts.laila(
fontWeight: FontWeight.w500,
fontSize: 30,
color: Colors.deepPurple),
),
Padding(
padding: const EdgeInsets.only(
left: 20.0, right: 20.0, top: 20.0, bottom: 20),
child: Column(
children: [
Stack(
children: [
Row(
children: [
Container(
decoration: BoxDecoration(
color: Color(0xffEFFAFF),
borderRadius:
BorderRadius.circular(20)),
child: Padding(
padding: const EdgeInsets.all(10.0),
child: Image.asset(
'assets/icon/suitcase.png'),
),
),
SizedBox(
width: 15,
),
Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Text(
'New Job started ',
style: GoogleFonts.poppins(
fontSize: 14,
fontWeight: FontWeight.w500,
color: Color(0xff151515)),
),
Text(
'Tailoring for John Cletus ',
style: GoogleFonts.poppins(
fontSize: 10,
fontWeight: FontWeight.w400,
color: Color(0xff151515)),
),
],
),
Spacer(),
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(2),
color: Color(0xffFFE8E8),
),
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
'Urgent',
style: GoogleFonts.poppins(
color: Color(0xffC95E5E)),
),
),
),
],
),
],
),
Divider(
height: 5,
color: Color(0xffEFFAFF),
),
],
),
),
],
),
),
current = 1 ?? Text('hello')
],
),
);
}
}
You can use Builder if want to display different type of widget based on the current index.
Builder(
builder: (context) {
switch (current) {
case 0:
return Container(
margin: const EdgeInsets.only(top: 30),
height: MediaQuery.of(context).size.height * 1,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const SizedBox(
height: 10,
),
Text(
items[current],
style: GoogleFonts.laila(
fontWeight: FontWeight.w500,
fontSize: 30,
color: Colors.deepPurple),
),
],
),
);
case 1:
return Text('Hello');
default:
return SizedBox.shrink();
}
},
);
Below approach will solve your problem. If you need further assistance, please feel free to comment.
int _currentIndex = 0;
var _containers = <Widget>[
AllContainer(),
JobsContainer(),
MessagesContainer(),
CustomerContainer(),
];
Widget _bottomTab() {
return BottomNavigationBar(
currentIndex: _currentIndex,
onTap: _onItemTapped, //
type: BottomNavigationBarType.fixed,
selectedLabelStyle: const TextStyle(color: Colors.blue),
selectedItemColor: WAPrimaryColor,
unselectedLabelStyle: const TextStyle(color: Colors.blue),
unselectedItemColor: Colors.grey,
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(label: 'All'),
BottomNavigationBarItem(
label: 'Jobs'),
BottomNavigationBarItem(
label: 'Messages'),
BottomNavigationBarItem( label: 'Customer'),
],
);
}
void _onItemTapped(int index) async {
print('bottom index::: $index');
setState(() {
_currentIndex = index;
});
}
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
bottomNavigationBar: _bottomTab(),
body: Center(child: _containers.elementAt(_currentIndex)),
),
);
}
You can use conditional if on widget level,
like
/// MAIN BODY
if (current == 0)
Container(
margin: const EdgeInsets.only(top: 30),
height: MediaQuery.of(context).size.height * 1,
...
),
if (current == 1) Text('hello')
Also can be use else if
if (current == 0)
Container(
margin: const EdgeInsets.only(top: 30),
height: MediaQuery.of(context).size.height * 1,
) //you shouldnt put coma
else if (current == 1) Text('hello')
],
),
);
But creating a separate method will be better instead of putting it here
Widget getWidget(int index) {
/// MAIN BODY
if (current == 0) // or switch case
return Container(
margin: const EdgeInsets.only(top: 30),
height: MediaQuery.of(context).size.height * 1,
); //you shouldnt put coma
else if (current == 1) return Text('hello');
return Text("default");
}
And call the method getWidget(current).
Also there are some widget like PageView, IndexedStack will help to organize the code structure

How can I fix the renderflex overflow of a card in Flutter?

How can I fix the RenderFlex overflowed pixel in my card Flutter? I cant seem to find a tutorial regarding this kind of problem. All of the tutorials in StackOverflow teach you to use the listview and SingleChildScrollView but that is not the case for me. The error shows in the card itself and I don't want the card to be using a singlechildscrollview.
I already tried fixing it by lowering the height and width but I will still need a proper tutorial that can help me fix this kind of issues.
This is the card.dart for the application
import 'package:flutter/material.dart';
class ListViewCard extends StatelessWidget {
final String title;
final void Function()? onTap;
final String imageOfPlant; //Change to String
const ListViewCard({
super.key,
required this.title,
required this.onTap,
required this.imageOfPlant,
});
#override
Widget build(BuildContext context) {
return Card(
color: const Color.fromARGB(255, 75, 175, 78),
elevation: 1,
margin: const EdgeInsets.all(8),
semanticContainer: true,
clipBehavior: Clip.antiAliasWithSaveLayer,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
),
child: InkWell(
splashColor: Colors.lightGreenAccent.withAlpha(30),
onTap: onTap,
//sizedBox of the card
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
//image of the card
Image.asset(
imageOfPlant,
height: 200,
width: 150,
fit: BoxFit.cover,
),
SizedBox(
height: 50,
width: 150,
child: Center(
child: Text(
title,
textAlign: TextAlign.center,
style: const TextStyle(
fontSize: 19,
fontFamily: 'RobotoMedium',
color: Color(0xffeeeeee)), // textstyle
),
),
), //text //SizedBox
], // <widget>[]
), // column
), //inkwell
); // card
}
}
This is the home.dart where the card will be called.
import 'package:flutter/material.dart';
import 'package:picleaf/nav_pages/plant.dart';
import '../widgets/card.dart';
class homePage extends StatefulWidget {
const homePage({super.key});
#override
State<homePage> createState() => _HomePageState();
}
List<String> plants = [
"Bell Pepper",
"Cassava",
"Grape",
"Potato",
"Strawberry",
"Tomato",
];
class CustomSearchDelegate extends SearchDelegate {
// Demo list to show querying
CustomSearchDelegate({String hinttext = "Search plants here"})
: super(searchFieldLabel: hinttext);
// first overwrite to
// clear the search text
#override
List<Widget>? buildActions(BuildContext context) {
return [
IconButton(
onPressed: () {
query = '';
},
icon: const Icon(Icons.clear),
),
];
}
// second overwrite to pop out of search menu
#override
Widget? buildLeading(BuildContext context) {
return IconButton(
onPressed: () {
close(context, null);
},
icon: const Icon(Icons.arrow_back),
);
}
// third overwrite to show query result
#override
Widget buildResults(BuildContext context) {
List<String> matchQuery = [];
for (var fruit in plants) {
if (fruit.toLowerCase().contains(query.toLowerCase())) {
matchQuery.add(fruit);
}
}
return ListView.builder(
itemCount: matchQuery.length,
itemBuilder: (context, index) {
var result = matchQuery[index];
return ListTile(
title: Text(
result,
style: const TextStyle(fontFamily: 'RobotoMedium'),
),
);
},
);
}
// last overwrite to show the
// querying process at the runtime
#override
Widget buildSuggestions(BuildContext context) {
List<String> matchQuery = [];
for (var fruit in plants) {
if (fruit.toLowerCase().contains(query.toLowerCase())) {
matchQuery.add(fruit);
}
}
return ListView.builder(
itemCount: matchQuery.length,
itemBuilder: (context, index) {
var result = matchQuery[index];
return ListTile(
title: Text(
result,
style: const TextStyle(fontFamily: 'RobotoMedium'),
),
);
},
);
}
}
class _HomePageState extends State<homePage> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
centerTitle: true,
title: const Text(
"PicLeaf",
style: TextStyle(
color: Color.fromRGBO(102, 204, 102, 1.0),
fontWeight: FontWeight.bold),
),
backgroundColor: Colors.white,
shadowColor: const Color.fromARGB(255, 95, 94, 94),
actions: [
IconButton(
onPressed: () {
// method to show the search bar
showSearch(
context: context,
// delegate to customize the search bar
delegate: CustomSearchDelegate());
},
icon: const Icon(Icons.search, color: Colors.black),
)
],
),
backgroundColor: const Color(0xffeeeeee),
body: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
const SizedBox(
height: 10,
),
Container(
padding: const EdgeInsets.fromLTRB(20, 20, 20, 10),
child: const Text(
'Take a pic!',
style: TextStyle(
fontSize: 35,
fontFamily: 'RobotoBold',
color: Colors.black),
textAlign: TextAlign.left,
),
),
Container(
padding: const EdgeInsets.fromLTRB(20, 0, 20, 10),
child: const Text('Find out what is wrong with your plant!',
style: TextStyle(
fontSize: 18,
fontFamily: 'RobotoMedium',
color: Color.fromRGBO(102, 124, 138, 1.0)),
textAlign: TextAlign.left),
),
const SizedBox(
height: 10,
),
Container(
color: const Color.fromRGBO(102, 204, 102, 1.0),
child: Column(
children: <Widget>[
Container(
padding: const EdgeInsets.fromLTRB(20, 10, 20, 0),
margin: const EdgeInsets.symmetric(horizontal: 0),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: const <Widget>[
Expanded(
child: Text('List of Plants',
style: TextStyle(
fontSize: 30,
fontFamily: 'RobotoBold',
color: Color(0xffeeeeee)),
textAlign: TextAlign.center),
),
],
),
),
GridView.count(
physics: const ScrollPhysics(),
shrinkWrap: true,
crossAxisSpacing: 20,
mainAxisSpacing: 20,
crossAxisCount: 2,
children: <Widget>[
ListViewCard(
title: "Bell Pepper",
onTap: () {
Navigator.of(context).push(MaterialPageRoute(
builder: (context) =>
const SecondPage(plantname: 'Bell Pepper')));
},
imageOfPlant:
"assets/Images_of_Plant/BellPeper_Image.jpg",
),
ListViewCard(
title: "Bell Pepper",
onTap: () {
Navigator.of(context).push(MaterialPageRoute(
builder: (context) =>
const SecondPage(plantname: 'Bell Pepper')));
},
imageOfPlant:
"assets/Images_of_Plant/BellPeper_Image.jpg",
),
ListViewCard(
title: "Bell Pepper",
onTap: () {
Navigator.of(context).push(MaterialPageRoute(
builder: (context) =>
const SecondPage(plantname: 'Bell Pepper')));
},
imageOfPlant:
"assets/Images_of_Plant/BellPeper_Image.jpg",
),
ListViewCard(
title: "Bell Pepper",
onTap: () {
Navigator.of(context).push(MaterialPageRoute(
builder: (context) =>
const SecondPage(plantname: 'Bell Pepper')));
},
imageOfPlant:
"assets/Images_of_Plant/BellPeper_Image.jpg",
),
ListViewCard(
title: "Bell Pepper",
onTap: () {
Navigator.of(context).push(MaterialPageRoute(
builder: (context) =>
const SecondPage(plantname: 'Bell Pepper')));
},
imageOfPlant:
"assets/Images_of_Plant/BellPeper_Image.jpg",
),
ListViewCard(
title: "Bell Pepper",
onTap: () {
Navigator.of(context).push(MaterialPageRoute(
builder: (context) =>
const SecondPage(plantname: 'Bell Pepper')));
},
imageOfPlant:
"assets/Images_of_Plant/BellPeper_Image.jpg",
),
],
),
],
),
),
],
),
),
);
}
}
Your gridView's Item give you a specific size but you are setting more than that for your container and text, I suggest you try this:
child: Stack(
children: <Widget>[
//image of the card
Image.asset(
imageOfPlant,
height: double.infinity,
width: 150,
fit: BoxFit.cover,
),
Positioned(
bottom: 0,
left: 0,
right: 0,
child: SizedBox(
height: 50,
width: 150,
child: Center(
child: Text(
title,
textAlign: TextAlign.center,
style: const TextStyle(
fontSize: 19,
fontFamily: 'RobotoMedium',
color: Color(0xffeeeeee)), // textstyle
),
),
),
), //text //SizedBox
], // <widget>[]
),
and If you want to change item's AspectRatio you can do this:
GridView.count(
physics: const ScrollPhysics(),
shrinkWrap: true,
crossAxisSpacing: 20,
mainAxisSpacing: 20,
crossAxisCount: 2,
childAspectRatio: 2 / 3, <--- add this
children: <Widget>[
...
]
)

how to store the name of the container in an array

hi i am new to flutter can anyone tell me how to save the preferences in an array
what are the methods used in storing the value
class PrefPage extends StatefulWidget {
#override
_PrefPageState createState() => _PrefPageState();
}
class _PrefPageState extends State<PrefPage> {
#override
Widget build(BuildContext context) {
return Scaffold(
bottomNavigationBar: Container(
color: Theme.of(context).backgroundColor,
padding: EdgeInsets.fromLTRB(10, 10, 30, 10),
height: 80,
child: Spring.bubbleButton(
onTap: () {
Navigator.push(
context, MaterialPageRoute(builder: (context) => Home()));
},
child: Text(
"👉",
style: TextStyle(fontSize: 30),
textAlign: TextAlign.end,
),
),
),
backgroundColor: Theme.of(context).backgroundColor,
appBar: AppBar(
centerTitle: false,
leadingWidth: 0,
elevation: 0,
backgroundColor: Theme.of(context).backgroundColor,
title: Text(
"Swoken",
style: GoogleFonts.niconne(
textStyle: TextStyle(
fontSize: 30,
color: Theme.of(context).primaryColor,
),
),
),
),
body: SingleChildScrollView(
physics: BouncingScrollPhysics(),
child: SafeArea(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
" What are your",
style: TextStyle(fontSize: 40, fontWeight: FontWeight.w100),
),
Text(
" Interests ?",
style: TextStyle(fontSize: 40, fontWeight: FontWeight.bold),
),
SizedBox(
height: 20,
),
GridView.count(
scrollDirection: Axis.vertical,
physics: ScrollPhysics(),
childAspectRatio: 2.3,
crossAxisCount: 2,
padding: EdgeInsets.all(5),
shrinkWrap: true,
children: List.generate(
intr.length,
(index) {
return PrefCont(
child: AutoSizeText(
intr[index]["icon"] + " " + intr[index]["title"],
minFontSize: 16,
maxLines: 1,
style: TextStyle(fontSize: 40),
),
);
},
),
),
],
),
),
),
);
}
}
class PrefCont extends StatefulWidget {
PrefCont({this.child});
final child;
#override
_PrefContState createState() => _PrefContState();
}
class _PrefContState extends State<PrefCont> {
List<String> sel = [];
bool isSelected = false;
#override
Widget build(BuildContext context) {
var themeId = DynamicTheme.of(context)!.themeId;
var kContColor = Color(0Xfff6f6f6);
themeId == 0
? kContColor = Color(0Xfff6f6f6)
: kContColor = Color(0xff272727);
return InkWell(
onTap: () {
setState(() {
isSelected = !isSelected;
});
},
child: Container(
alignment: Alignment.center,
decoration: BoxDecoration(
color: isSelected ? kContInactColor : kContColor,
borderRadius: BorderRadius.circular(10),
),
margin: EdgeInsets.all(10),
padding: EdgeInsets.all(10),
child: widget.child,
),
);
}
}
...........................................................................................................................................................................................................................................................................
First you need to modelize your elements as objects then, you need to create a data set containing all of your tiles:
class PreferencesData {
final String name;
final String assetName;
PreferencesData({required this.name, required this.assetName});
}
list _dataSet = [
PreferencesData(name: "Football", assetName: "/assets/icons/football.png"),
PreferencesData(name: "Food", assetName: "/assets/icons/food.png"),
...
];
Now that you have all your objects in a dataset you can use it in your grid to display them correctly:
children: [for (PreferencesData pref in _dataSet)
PrefCont(...) // access your data with pref.name
]

Ripple effect appears under custem listview item on click in Flutter

I have tried many solutions from this platform and others too but my problem remains the same. I have done this before and successfully ripple the listview item in another custom listview. But this time i am not getting any clue where i am lacking. The previous solution make things more messy if try this time. Ripple is appearing under listview item what i want is to only listview item do ripples.
class Dashboard extends StatefulWidget {
#override
_DashboardState createState() => _DashboardState();
}
class _DashboardState extends State<Dashboard> {
// Map<String, dynamic> args;
List<DashboardItem> lst = [
DashboardItem(
img: 'assets/sales.png', name: 'Sales', subtitle: 'Your daily sales'),
DashboardItem(
img: 'assets/order.png', name: 'Orders', subtitle: 'Your new orders'),
DashboardItem(
img: 'assets/report.png',
name: 'Reports',
subtitle: 'Your daily reports'),
DashboardItem(
img: 'assets/setting.png',
name: 'Setting',
subtitle: 'Application setting'),
DashboardItem(
img: 'assets/register.png',
name: 'Register',
subtitle: 'Close your register'),
DashboardItem(
img: 'assets/logout.png', name: 'Logout', subtitle: 'You can rest')
];
#override
Widget build(BuildContext context) {
// args = ModalRoute.of(context).settings.arguments;
// print('Dashboard : ${args['regId']}');
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.red,
elevation: 0.0,
title: Text('My Dashboard'),
centerTitle: true,
),
body: LayoutBuilder(
builder: (context, constraints){
if(constraints.maxWidth < 600){
return ListView.builder(
itemCount: lst.length,
shrinkWrap: true,
itemBuilder: (context, position){
return Container(
padding: position == lst.length ? const EdgeInsets.only(top:16.0) : const EdgeInsets.only(top:16.0, bottom: 16.0),
child: InkWell(
child: DashboardCard(lst[position]),
onTap: (){
Toast.show('In List', context);
},
),
);
},
);
}
else{
return GridView.builder(
itemCount: lst.length,
shrinkWrap: true,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2),
itemBuilder: (context, position){
return InkWell(
child: DashboardCard(lst[position]),
onTap: (){
Toast.show('In Grid', context);
},
);
},
);
}
},
),
);
}
}
DashboardCard Class
class DashboardCard extends StatelessWidget {
final DashboardItem _dashboardItem;
const DashboardCard(this._dashboardItem);
#override
Widget build(BuildContext context) {
return Center(
child: Container(
height: 230,
width: 280,
child: Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
),
elevation: 10.0,
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Image(
image: AssetImage(_dashboardItem.img),
fit: BoxFit.contain,
width: 80,
height: 80,
),
SizedBox(height: 20,),
Text(
_dashboardItem.name,
style: TextStyle(
fontSize: 25,
fontWeight: FontWeight.bold,
fontFamily: 'Ubuntu',
letterSpacing: 2.0,
color: Colors.redAccent,
),
),
Padding(
padding: const EdgeInsets.all(3.0),
child: Text(
_dashboardItem.subtitle,
maxLines: 2,
textAlign: TextAlign.center,
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontSize: 10,
fontWeight: FontWeight.normal,
letterSpacing: 2.0,
color: Colors.grey,
),
),
),
],
),
),
),
),
);
}
}
The issue is with the Center widget in your DashboardCard:
You can fix it wrapping your DashboardCard Container widget in an InkWell widget and pass a onTap parameter to the DashboardCard constructor:
class DashboardCard extends StatelessWidget {
final DashboardItem _dashboardItem;
final VoidCallback onTap;
const DashboardCard(
this._dashboardItem, {
this.onTap,
});
#override
Widget build(BuildContext context) {
return Center(
child: InkWell(
onTap: onTap,
child: Container(
height: 230,
width: 280,
child: Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
),
elevation: 10.0,
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Image(
image: AssetImage(_dashboardItem.img),
fit: BoxFit.contain,
width: 80,
height: 80,
),
SizedBox(
height: 20,
),
Text(
_dashboardItem.name,
style: TextStyle(
fontSize: 25,
fontWeight: FontWeight.bold,
fontFamily: 'Ubuntu',
letterSpacing: 2.0,
color: Colors.redAccent,
),
),
Padding(
padding: const EdgeInsets.all(3.0),
child: Text(
_dashboardItem.subtitle,
maxLines: 2,
textAlign: TextAlign.center,
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontSize: 10,
fontWeight: FontWeight.normal,
letterSpacing: 2.0,
color: Colors.grey,
),
),
),
],
),
),
),
),
),
);
}
}
The use it in other places like:
DashboardCard(
lst[position],
onTap: () {
Toast.show('In List', context);
},
),

How to change a bottom navigation bar icon in the setState() function in flutter?

I'm building a food ordering app in flutter. What I want is, when the user adds items to the cart, I want the cart icon in the bottom navigation bar to obtain a red dot on top to notify the user of the addition of items to the cart.
To achieve this, I have created a global variable called no_of_cart_items and when the user adds an item to the cart, I increment this variable in the setState() function as follows:
setState(() {
GlobalVariables.no_of_cart_items+=1;
// change icon here
});
In this setState() function, I wish to change the icon in the bottom navigation bar. How should I do this?
Thank you.
FULL CODE
This is main.dart
//import lines
void main() => runApp(CanteenApp());
class CanteenApp extends StatefulWidget {
#override
_CanteenAppState createState() => _CanteenAppState();
}
class _CanteenAppState extends State<CanteenApp> {
int _currentindex=0; // index of bottom tab
int admin=GlobalVariables.admin;
BottomNavigationBadge badger = new BottomNavigationBadge(
backgroundColor: Colors.red,
badgeShape: BottomNavigationBadgeShape.circle,
textColor: Colors.white,
position: BottomNavigationBadgePosition.topRight,
textSize: 8);
Widget callpage(int currentIndex) {
switch (currentIndex) {
case 0: return UserProfile();
case 1: return Menu();
case 2: return Cart();
break;
default: return UserProfile();
}
}
#override
Widget build(BuildContext context) {
if(admin==1 && _currentindex==2) {
//if you're the admin and have called the history page
return MaterialApp(
debugShowCheckedModeBanner: false,
home: DefaultTabController(
length: 2,
child: Scaffold(
resizeToAvoidBottomPadding: false,
appBar: PreferredSize(
preferredSize: Size.fromHeight(80.0),
child: AppBar(
bottom: TabBar(
indicatorColor: Colors.white,
indicatorWeight: 5,
tabs: <Widget>[
Tab(
child: Align(
alignment: Alignment.center,
child: Text(
'Order History',
style: TextStyle(
fontSize: 20
),
)
)
),
Tab(
child: Align(
alignment: Alignment.center,
child: Text(
'Deposit / Withdraw\nHistory',
style: TextStyle(
fontSize: 17
),
textAlign: TextAlign.center,
)
)
),
],
),
),
),
body: TabBarView(
children: <Widget>[
AdminOrderHistory(),
DepositWithdrawHistory()
],
),
bottomNavigationBar: BottomNavigationBar(
elevation: 10,
currentIndex: _currentindex,
items: [
BottomNavigationBarItem(
icon: Icon(Icons.account_circle),
title: Text('Profile'),
),
BottomNavigationBarItem(
icon: Icon(Icons.restaurant_menu),
title: Text('Menu'),
),
BottomNavigationBarItem(
icon: Icon(Icons.history),
title: Text('History'),
),
],
onTap: (index){
setState(() {
_currentindex=index;
});
}
),
),
),
theme: appTheme,
);
}
else if(admin==1){
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
resizeToAvoidBottomPadding: false,
body: callpage(_currentindex),
bottomNavigationBar: BottomNavigationBar(
elevation: 10,
currentIndex: _currentindex,
items: [
BottomNavigationBarItem(
icon: Icon(Icons.account_circle),
title: Text('Profile'),
),
BottomNavigationBarItem(
icon: Icon(Icons.restaurant_menu),
title: Text('Menu'),
),
BottomNavigationBarItem(
icon: Icon(Icons.history),
title: Text('History'),
),
],
onTap: (index){
setState(() {
_currentindex=index;
});
}
),
),
theme: appTheme,
);
}
else if(admin==0){
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
resizeToAvoidBottomPadding: false,
body: callpage(_currentindex),
bottomNavigationBar:BottomNavigationBar(
elevation: 10,
currentIndex: _currentindex,
items: [
BottomNavigationBarItem(
icon: Icon(Icons.account_circle),
title: Text('Profile'),
),
BottomNavigationBarItem(
icon: Icon(Icons.restaurant_menu),
title: Text('Menu'),
),
BottomNavigationBarItem(
title: Text('Cart'),
icon: Badge(
showBadge: true,
badgeContent: Text(
GlobalVariables.no_of_cart_items.toString(),
style: TextStyle(
color: Colors.white
),
),
child: Icon(Icons.shopping_cart)
)
),
],
onTap: (index){
setState(() {
_currentindex=index;
});
}
),
),
theme: appTheme,
);
}
}
}
This is menu.dart
//import lines
int admin=GlobalVariables.admin;
List snacksmenuitems=[
['Vada Pav', 15],
['Samosa Pav', 15],
['Punjabi Samosa', 25],
['Pav', 5]
];
List ricemenuitems=[
['Fried Rice', 62],
['Schezwan Rice', 69],
['Singapore Rice', 69],
['Manchow Rice', 73],
];
class Menu extends StatefulWidget {
#override
_MenuState createState() => _MenuState();
}
class _MenuState extends State<Menu> {
#override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
MenuTopPart(),
MenuBottomPart(),
],
);
}
}
Color firstColor = Color(0xFFF47D15);
Color secondColor = Color(0xFFEF772C);
class MenuTopPart extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Stack(
children: <Widget>[
ClipPath(
clipper: CustomShapeClipper(),
child: Container(
height:140.0,
width:MediaQuery.of(context).size.width,
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [firstColor, secondColor],
)
),
child: Column(
children: <Widget>[
SizedBox(height: 53.0),
Text(
'MENU',
style: TextStyle(
fontSize: 30.0,
color: Colors.white,
),
textAlign: TextAlign.center,
),
],
)
)
)
],
);
}
}
class MenuBottomPart extends StatefulWidget {
#override
_MenuBottomPartState createState() => _MenuBottomPartState();
}
class _MenuBottomPartState extends State<MenuBottomPart> {
#override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
SizedBox(height: 10),
SizedBox(height: 10),
Padding(
padding: const EdgeInsets.fromLTRB(20, 0, 20, 10),
child: Container(
height: MediaQuery
.of(context)
.size
.height * 0.60,
child: ListView(
padding: EdgeInsets.fromLTRB(0, 0, 0, 0),
scrollDirection: Axis.vertical,
children: <Widget>[
Card(
child: Padding(
padding: const EdgeInsets.fromLTRB(5, 0, 5, 0),
child: ExpansionTile(
title: Text('SNACKS'),
children: snacksmenuitems.map((menuitem) {
//print(menuitem);
return MenuItem(menuitem: menuitem);
/*SizedBox(height:10),
MenuItem(),
SizedBox(height:10),
MenuItem(),
SizedBox(height:10),
MenuItem()*/
}).toList()
),
)
),
SizedBox(height: 10),
Card(
child: Padding(
padding: const EdgeInsets.fromLTRB(5, 0, 5, 0),
child: ExpansionTile(
title: Text('RICE ITEMS'),
children: ricemenuitems.map((menuitem) {
//print(menuitem);
return MenuItem(menuitem: menuitem);
/*SizedBox(height:10),
MenuItem(),
SizedBox(height:10),
MenuItem(),
SizedBox(height:10),
MenuItem()*/
}).toList()
),
)
)
]
),
),
)
]
);
}
}
class MenuItem extends StatefulWidget {
List menuitem=[];
MenuItem({Key key, this.menuitem}): super(key: key);
#override
_MenuItemState createState() => _MenuItemState();
}
class _MenuItemState extends State<MenuItem> {
#override
Widget build(BuildContext context) {
return Container(
margin: const EdgeInsets.only(bottom: 10),
decoration: BoxDecoration(
border: Border.all(color: Colors.black12),
borderRadius: BorderRadius.all(Radius.circular(10))
),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Image(
image: NetworkImage('https://www.whiskaffair.com/wp-content/uploads/2018/08/Mumbai-Pav-Bhaji-4.jpg'),
width: 80,
height: 80
),
SizedBox(width:10),
Padding(
padding: const EdgeInsets.fromLTRB(0, 5, 0, 0),
child: Container(
width:190,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
widget.menuitem[0],
style: TextStyle(
fontSize:19,
color: Colors.grey[900]
),
),
SizedBox(height:5.0),
Padding(
padding: const EdgeInsets.fromLTRB(0, 10, 0, 0),
child: Row(
children: <Widget>[
Row(
children: <Widget>[
Text(
'₹',
style: TextStyle(
fontSize: 15,
color: Colors.grey[800]
),
),
Text(
widget.menuitem[1].toString(),
style: TextStyle(
fontSize: 15,
color: Colors.grey[800]
),
)
],
),
SizedBox(width:70),
Container(
child: Row(
children: <Widget>[
SizedBox(
width:30,
height:30,
child: FloatingActionButton(
onPressed: (){
setState(() {
if(GlobalVariables.allcartitems[widget.menuitem[0]][0]>0){
GlobalVariables.no_of_cart_items-=1;
GlobalVariables.allcartitems[widget.menuitem[0]][0]-=1;
GlobalVariables.totalcost-=GlobalVariables.allcartitems[widget.menuitem[0]][1];
// CHECK IF CART HAS NO ITEMS AND REMOVE BADGE HERE
}
});
},
elevation: 1,
child: Icon(Icons.remove, size: 18),
backgroundColor: Colors.red[300],
mini: true,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(5.0))),
),
),
Padding(
padding: const EdgeInsets.fromLTRB(5, 0, 5, 0),
child: Text(
GlobalVariables.allcartitems[widget.menuitem[0]][0].toString(),
style: TextStyle(
fontSize: 18
),
),
),
SizedBox(
width:30,
height:30,
child: FloatingActionButton(
onPressed: (){
setState(() {
GlobalVariables.no_of_cart_items+=1;
GlobalVariables.allcartitems[widget.menuitem[0]][0]+=1;
GlobalVariables.totalcost+=GlobalVariables.allcartitems[widget.menuitem[0]][1];
// SET BADGE HERE
});
},
elevation: 1,
child: Icon(Icons.add, size: 20),
backgroundColor: Colors.green[300],
mini:true,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(5.0))),
),
)
],
)
)
],
),
),
],
),
),
)
],
),
);
}
}
This is cart.dart:
import 'dart:convert';
import 'package:canteen_app/pages/globalvar.dart';
import 'package:canteen_app/pages/globalvar.dart' as prefix0;
import 'package:canteen_app/pages/orderReceipt.dart';
import 'package:flutter/material.dart';
import 'package:canteen_app/pages/CustomShapeClipper.dart';
import 'package:http/http.dart' as http;
import 'package:intl/intl.dart';
class Cart extends StatefulWidget {
#override
_CartState createState() => _CartState();
}
class _CartState extends State<Cart> {
#override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
CartTopPart(),
CartBottomPart()
],
);
}
}
class CartTopPart extends StatefulWidget {
#override
_CartTopPartState createState() => _CartTopPartState();
}
Color firstColor = Color(0xFFF47D15);
Color secondColor = Color(0xFFEF772C);
class _CartTopPartState extends State<CartTopPart> {
#override
Widget build(BuildContext context) {
return Stack(
children: <Widget>[
ClipPath(
clipper: CustomShapeClipper(),
child: Container(
height:140.0,
width:MediaQuery.of(context).size.width,
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [firstColor, secondColor],
)
),
child: Column(
children: <Widget>[
SizedBox(height: 53.0),
Text(
'CART',
style: TextStyle(
fontSize: 30.0,
color: Colors.white,
),
textAlign: TextAlign.center,
),
],
)
)
)
],
);
}
}
var cartmenuitems = GlobalVariables.allcartitems.keys.toList();
class CartBottomPart extends StatefulWidget {
#override
_CartBottomPartState createState() => _CartBottomPartState();
}
class _CartBottomPartState extends State<CartBottomPart> {
bool _isLoading=false;
createAlertDialog(BuildContext context, String errormessage){
return showDialog(
context: context,
builder: (context){
return AlertDialog(
content: Text(errormessage)
);
}
);
}
#override
Widget build(BuildContext context) {
if(GlobalVariables.no_of_cart_items>0) {
return _isLoading==true ? Center(child: CircularProgressIndicator()) : Padding(
padding: const EdgeInsets.fromLTRB(20, 10, 20, 10),
child: Column(
children: <Widget>[
Container(
height: MediaQuery
.of(context)
.size
.height * 0.40,
child: ListView(
padding: EdgeInsets.fromLTRB(0, 10, 0, 0),
scrollDirection: Axis.vertical,
children: cartmenuitems.map((menuitem) {
//print(cartmenuitems);
// print(GlobalVariables.allcartitems[menuitem]);
//if(GlobalVariables.allcartitems[menuitem]>=1) {
//print('heyy');
return CartOrderDish(menuitem: menuitem);
//}
}).toList()
),
),
Divider(
color: Colors.black
),
Row(
children: <Widget>[
Text(
'Total Amount:',
style: TextStyle(
fontSize: 20
),
),
SizedBox(width: 140),
Row(
children: <Widget>[
Text(
'₹',
style: TextStyle(
fontSize: 20
),
),
Text(
GlobalVariables.totalcost.toString(),
style: TextStyle(
fontSize: 20
)
)
],
)
],
),
SizedBox(height: 5),
Align(
alignment: Alignment.centerLeft,
child: Text(
'(Inclusive of GST)',
style: TextStyle(
fontSize: 15
),
),
),
SizedBox(height: 18),
RaisedButton(
onPressed: () {
if((GlobalVariables.accountbalance-GlobalVariables.totalcost)<0){
createAlertDialog(context, "Whoops! The total cost exceeds your account balance!\n\nYour account balance can be updated at the CASH COUNTER.");
}
else {
setState(() {
_isLoading = true;
});
// creating a list of all cart items to send to php
List cart = [];
cartmenuitems.map((menuitem) {
if (GlobalVariables.allcartitems[menuitem][0] > 0) {
cart.add([menuitem, GlobalVariables.allcartitems[menuitem][0], GlobalVariables.allcartitems[menuitem][1] * GlobalVariables.allcartitems[menuitem][0]]);
}
}).toList();
print(jsonEncode(cart));
Future placeOrderFunction() async {
print(GlobalVariables.username);
final response = await http.post(
"https://kjscecanteenapp.000webhostapp.com/place_order_sys.php",
body: {
"cart": json.encode(cart),
"username": GlobalVariables.username
});
// print(response.body);
var decodedResponse = json.decode(response.body);
print(decodedResponse);
setState(() {
_isLoading = false;
});
if (decodedResponse['error'] != -1) {
// means no error
int orderId=decodedResponse['error'];
int cost=GlobalVariables.totalcost;
GlobalVariables.no_of_cart_items = 0;
String date=DateFormat('dd-MMM-yyyy').format(DateTime.now());
cartmenuitems.map((menuitem) {
if (GlobalVariables.allcartitems[menuitem][0] > 0) {
GlobalVariables.allcartitems[menuitem][0] = 0;
}
});
GlobalVariables ob = new GlobalVariables();
ob.resetcart();
GlobalVariables.accountbalance -= GlobalVariables.totalcost;
GlobalVariables.totalcost = 0;
Navigator.of(context)
.push(MaterialPageRoute<Null>(
builder: (BuildContext context) {
return new OrderReceipt(orderId: orderId, cost: cost, date: date, cart: cart);
}));
}
else{
createAlertDialog(context, "There was some error during the order placement. Don't worry tho try again in a few seconds!");
}
}
placeOrderFunction();
}
},
elevation: 5.0,
textColor: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(5.0)),
padding: const EdgeInsets.all(0.0),
child: Container(
decoration: const BoxDecoration(
gradient: LinearGradient(
colors: <Color>[
Color(0xFF0083B0),
Color(0xFF00B4DB),
]
)
),
padding: const EdgeInsets.fromLTRB(40, 15, 40, 15),
child: Text(
'Place Order',
style: TextStyle(
fontSize: 20
),
),
)
)
],
),
);
}
else {
return Padding(
padding: const EdgeInsets.all(20.0),
child: Container(
height: MediaQuery.of(context).size.height*0.6,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Text(
'Please add some items into your cart.',
style: TextStyle(
fontSize: 20,
),
textAlign: TextAlign.center,
),
],
),
),
);
}
}
}
class CartOrderDish extends StatefulWidget {
String menuitem;
CartOrderDish({Key key, this.menuitem}): super(key: key);
#override
_CartOrderDishState createState() => _CartOrderDishState();
}
class _CartOrderDishState extends State<CartOrderDish> {
#override
Widget build(BuildContext context) {
if(GlobalVariables.allcartitems[widget.menuitem][0]>0) {
int price=GlobalVariables.allcartitems[widget.menuitem][0]*GlobalVariables.allcartitems[widget.menuitem][1];
return Padding(
padding: const EdgeInsets.fromLTRB(0, 0, 0, 10),
child: Row(
children: <Widget>[
Expanded(
child: Text(
widget.menuitem,
style: TextStyle(
fontSize: 20
),
),
),
SizedBox(width: 50),
Container(
child: Row(
children: <Widget>[
SizedBox(
width: 30,
height: 30,
child: FloatingActionButton(
heroTag: 'fab1',
elevation: 1,
child: Icon(Icons.remove, size: 18),
backgroundColor: Colors.red[300],
mini: true,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(5.0))),
),
),
Padding(
padding: const EdgeInsets.fromLTRB(5, 0, 5, 0),
child: Text(
GlobalVariables.allcartitems[widget.menuitem][0].toString(),
style: TextStyle(
fontSize: 18
),
),
),
SizedBox(
width: 30,
height: 30,
child: FloatingActionButton(
heroTag: 'fab2',
elevation: 1,
child: Icon(Icons.add, size: 20),
backgroundColor: Colors.green[300],
mini: true,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(5.0))),
),
)
],
)
),
SizedBox(width: 50),
Row(
children: <Widget>[
Text(
'₹',
style: TextStyle(
fontSize: 20
),
),
Text(
price.toString(),
style: TextStyle(
fontSize:20
)
)
],
)
],
),
);
}
else{
return Container();
}
}
}
Instead of changing the entire icon to indicate items added to cart, you could use Badge
Badge package: https://pub.dev/packages/badges
Update-1: For implementing the badges:
var p1badge = false;
var p2badge = false;
List<BottomNavigationBarItem> buildBottomNavBarItems() {
return [
BottomNavigationBarItem(
icon: Badge(
showBadge: p1badge,
child: Icon(Icons.filter_1),
),
title: Text('Page-1')),
BottomNavigationBarItem(
icon: Badge(
showBadge: p2badge,
child: Icon(Icons.filter_2),
),
title: Text('Page-2'))
];
}
Use a VoidCallback to update the badge:
class Page1 extends StatelessWidget {
VoidCallback onP1Badge;
Page1({this.onP1Badge});
#override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
RaisedButton(
child: Text('P1 BADGE'),
onPressed: () {onP1Badge();},
),
],
);
}
}
Change the value of p1badge to true and call setState():
pages = [
Page1(
onP1Badge: () {
p1badge = true;
setState(() {});
},
),
Page2()
];
Update-2: Check this out: https://github.com/TheArhaam/Flutter-BottomNavigationBar-Badge
GIF: