Like in my sample image, below, I want to increment or decrement quantity upon button click for single list item. If I increase the counter in setState(), its incrementing in every list item. I need help with this, especially in handling specific list item in Flutter.
![Sample Image][2]
Any help is appreciated.
Thanks in advance.
Got the List Item Thanks for the help,
Turn _counter into a list and add an item for each item in your listView. builder to it. And when changing, change _counter [i]; And so will change that specific item! Hope this helps!
A flutter widget that accepts numbers along with buttons to increment and decrement. This is a simple TextFormField with buttons and logic to handle factored increments/decrements and with some additional properties like minimum and maximum allowed value.
All you need to do is to refactor your widgets the proper way. You can refactor your Card
s / items into their separate StatefulWdiget
such that each increment/decrement affect only a specific item and not the whole list.
Check this example :
class FlutterExample extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new Scaffold(
body: new ListView(
children: new List.generate(5, (i)=>new ListTileItem(
title: "Item#$i",
)),
),
);
}
}
class ListTileItem extends StatefulWidget {
String title;
ListTileItem({this.title});
@override
_ListTileItemState createState() => new _ListTileItemState();
}
class _ListTileItemState extends State<ListTileItem> {
int _itemCount = 0;
@override
Widget build(BuildContext context) {
return new ListTile(
title: new Text(widget.title),
trailing: new Row(
children: <Widget>[
_itemCount!=0? new IconButton(icon: new Icon(Icons.remove),onPressed: ()=>setState(()=>_itemCount--),):new Container(),
new Text(_itemCount.toString()),
new IconButton(icon: new Icon(Icons.add),onPressed: ()=>setState(()=>_itemCount++))
],
),
);
}
}
If you planning to get only the UI code. here is the code to build such a beautiful button.
Code:
Container(
padding: EdgeInsets.all(3),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5),
color: Theme.of(context).accentColor),
child: Row(
children: [
InkWell(
onTap: () {},
child: Icon(
Icons.remove,
color: Colors.white,
size: 16,
)),
Container(
margin: EdgeInsets.symmetric(horizontal: 3),
padding:
EdgeInsets.symmetric(horizontal: 3, vertical: 2),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(3),
color: Colors.white),
child: Text(
'3',
style: TextStyle(color: Colors.black, fontSize: 16),
),
),
InkWell(
onTap: () {},
child: Icon(
Icons.add,
color: Colors.white,
size: 16,
)),
],
),
),
I was facing the same problem and made a reusable thing:
class QuantityButton extends StatefulWidget {
final int initialQuantity;
final Future<int>? Function(int) onQuantityChange;
const QuantityButton(
{Key? key, required this.initialQuantity, required this.onQuantityChange})
: super(key: key);
@override
_QuantityButtonState createState() =>
_QuantityButtonState(quantity: initialQuantity);
}
class _QuantityButtonState extends State<QuantityButton> {
int quantity;
bool isSaving = false;
_QuantityButtonState({required this.quantity});
void changeQuantity(int newQuantity) async {
setState(() {
isSaving = true;
});
newQuantity = await widget.onQuantityChange(newQuantity) ?? newQuantity;
setState(() {
quantity = newQuantity;
isSaving = false;
});
}
@override
Widget build(BuildContext context) {
return Row(children: [
IconButton(
color: Colors.black,
onPressed: (isSaving || quantity < 1)
? null
: () => changeQuantity(quantity - 1),
icon: Icon(Icons.remove)),
Text(quantity.toString()),
IconButton(
color: Colors.black,
onPressed: (isSaving) ? null : () => changeQuantity(quantity + 1),
icon: Icon(Icons.add)),
]);
}
}
You can now use it as simple as:
Row(
children: [
Text(basketLine.product.title),
Spacer(),
QuantityButton(
initialQuantity: basketLine.quantity,
onQuantityChange: basketLine.updateQuantity,
),
],
)
While updateQuantity could update the basket asynchronous (if you want the +/- button to be disabled to make sure e.g. the backend validation passes) and return the updated number, or simply trigger the update, return null (and not await it) to let the widget handle the number for a more real time experience.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With