Reputation: 55
I want to increase the quantity when '+' icon se clicked and decrease the quantity when '-' icon is clicked in the ListView.builder(). But my code changes quantity of all listview items whichever icon I clicked. I'm new to Flutter and Dart. I want to change the data of particular row when user taps either '+' or '-' icon of that particular row.
Please help me to resolve my issue.
Here is my code -:
import 'package:flutter/material.dart';
import 'package:flutter_testing/InkWellGesture.dart';
class Cart extends StatefulWidget {
Cart({Key key}) : super(key: key);
@override
_CartState createState() => _CartState();
}
class _CartState extends State<Cart> {
int qty = 1;
int items = 2;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Cart'),
),
body: Column(
children: <Widget>[
Container(
padding: EdgeInsets.only(
left: 3,
),
height: 60,
child: Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8)),
elevation: 3,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Expanded(
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
margin: EdgeInsets.only(left: 3, top: 7, right: 6),
width: 13,
height: 15,
decoration: BoxDecoration(
shape: BoxShape.circle, color: Colors.green),
),
Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text('Deliver to NAME address line 1...',
style: TextStyle(fontSize: 15)),
Text('click here to change address',
style: TextStyle(
fontSize: 12, color: Colors.grey)),
],
),
],
),
),
Icon(Icons.keyboard_arrow_right),
],
),
),
),
Expanded(
child: ListView.builder(
itemCount: items,
itemBuilder: (ctx, itemIndex) {
return Card(
elevation: 3,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15)),
child: Container(
height: 65,
margin: EdgeInsets.symmetric(vertical: 5, horizontal: 5),
child: Row(
children: <Widget>[
Container(
width: 65,
height: 65,
decoration: BoxDecoration(
border:
Border.all(color: Colors.grey, width: 1),
borderRadius:
BorderRadius.all(Radius.circular(10))),
),
Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Padding(
padding:
const EdgeInsets.only(left: 10, right: 7),
child: Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: <Widget>[
Text('Item Name',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold)),
Text(
'\u{20B9} 9,999',
style: TextStyle(fontSize: 18),
),
],
),
),
Padding(
padding: const EdgeInsets.only(right: 4),
child: Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: <Widget>[
Expanded(
child: Row(
mainAxisAlignment:
MainAxisAlignment.spaceEvenly,
children: <Widget>[
inkWellGesture(
() {
setState(() {
qty += 1;
});
},
child: Icon(
Icons.add_circle,
color: Colors.green,
size: 25,
),
),
Text(
qty > 0 ? qty.toString() : '1',
style: TextStyle(fontSize: 16),
),
inkWellGesture(
() {
setState(() {
qty -= 1;
});
},
child: Icon(
Icons.remove_circle,
color: Colors.red,
size: 25,
),
)
],
),
),
Expanded(
flex: 2,
child: Row(
mainAxisAlignment:
MainAxisAlignment.end,
children: [
Icon(
Icons.delete_forever,
color: Colors.red,
size: 25,
),
],
),
)
],
),
),
],
),
),
],
),
),
);
}),
),
Container(
height: 200,
padding: const EdgeInsets.only(top: 15, left: 15, right: 15),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
TextField(
obscureText: true,
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'Promo Code',
)),
Expanded(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text('Shipping'),
Text('Offer'),
Text('Tax'),
Text('Sub Total'),
],
),
Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(' \u{20B9} 80'),
Text('- \u{20B9} 100'),
Text(' \u{20B9} 1,799'),
Text(' \u{20B9} 8,200')
],
),
],
),
),
],
),
),
Align(
alignment: Alignment.bottomCenter,
child: Container(
width: double.infinity,
child: FlatButton(
child: Text('PROCEED TO \u{20B9} 10,019',
style: TextStyle(fontSize: 20)),
onPressed: () {},
color: Colors.green,
textColor: Colors.white,
))),
],
),
);
}
Here is the screenshot -:
Upvotes: 1
Views: 3270
Reputation: 1609
Make sure you're getting the item's quantity by its index (itemBuilder: (ctx, itemIndex)
). Try this:
Expanded(
child: ListView.builder(
itemCount: items,
itemBuilder: (ctx, itemIndex) {
return Card(
elevation: 3,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15)),
child: Container(
height: 65,
margin: EdgeInsets.symmetric(vertical: 5, horizontal: 5),
child: Row(
children: <Widget>[
Container(
width: 65,
height: 65,
decoration: BoxDecoration(
border:
Border.all(color: Colors.grey, width: 1),
borderRadius:
BorderRadius.all(Radius.circular(10))),
),
Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Padding(
padding:
const EdgeInsets.only(left: 10, right: 7),
child: Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(items[itemIndex].name,
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold)),
Text(
'\u{20B9} ${items[itemIndex].amount}',
style: TextStyle(fontSize: 18),
),
],
),
),
Padding(
padding: const EdgeInsets.only(right: 4),
child: Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: <Widget>[
Expanded(
child: Row(
mainAxisAlignment:
MainAxisAlignment.spaceEvenly,
children: <Widget>[
inkWellGesture(
() {
setState(() {
items[itemIndex].quantity += 1;
});
},
child: Icon(
Icons.add_circle,
color: Colors.green,
size: 25,
),
),
Text(
items[itemIndex].quantity > 0 ? items[itemIndex].quantity.toString() : '1',
style: TextStyle(fontSize: 16),
),
inkWellGesture(
() {
setState(() {
items[itemIndex].quantity -= 1;
});
},
child: Icon(
Icons.remove_circle,
color: Colors.red,
size: 25,
),
)
],
),
),
Expanded(
flex: 2,
child: Row(
mainAxisAlignment:
MainAxisAlignment.end,
children: [
Icon(
Icons.delete_forever,
color: Colors.red,
size: 25,
),
],
),
)
],
),
),
],
),
),
],
),
),
);
}),
),
Upvotes: 1
Reputation: 7328
All the values change because they all refer to the same qty
variable. Each of your list item should have its own value. A way to do this would be to create a class containing all the data of your item.
class CardItem {
String name;
int qty;
String price;
// I've defined some default values but it could be anything else
CardItem({@required this.name, this.qty = 1, this.price = "9,999"});
}
Then you could generate a list of CardItem
to build your ListView
.
List<CardItem> _listItems = [];
int items = 2;
@override
void initState() {
super.initState();
for (int i = 0; i < items; i++) _listItems.add(CardItem(name: "Item Name $i", qty: 2));
}
// ...
// For the item name and price
Text(
_listItems[itemIndex].name,
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
Text(
'\u{20B9} ${_listItems[itemIndex].price}',
style: TextStyle(fontSize: 18),
),
// To add or remove
inkWellGesture(
() {
setState(() => _listItems[itemIndex].qty += 1);
},
child: Icon(
Icons.add_circle,
color: Colors.green,
size: 25,
),
),
Text(
_listItems[itemIndex].qty > 0 ? _listItems[itemIndex].qty.toString() : '1',
style: TextStyle(fontSize: 16),
),
inkWellGesture(
() {
setState(() => _listItems[itemIndex].qty -= 1);
},
child: Icon(
Icons.remove_circle,
color: Colors.red,
size: 25,
),
),
Upvotes: 1
Reputation: 4783
Create an array of quantity having the same size that your items. Associate each item qty to the corresponding quantity array index.
int items = 2;
List<int> qties = [];
@override
void initState () {
for (int i = 0; i < items; ++ i) qties.add(1);
}
// ...
inkWellGesture(
() {
setState(() {
qties[itemIndex] += 1;
});
},
child: Icon(
Icons.add_circle,
color: Colors.green,
size: 25,
),
),
Text(
qties[itemIndex] > 0 ? qties[itemIndex].toString() : '1',
style: TextStyle(fontSize: 16),
),
inkWellGesture(
() {
setState(() {
qties[itemIndex] -= 1;
});
},
child: Icon(
Icons.remove_circle,
color: Colors.red,
size: 25,
),
),
Upvotes: 1