Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to increment counter for a specific list item in Flutter?

Tags:

flutter

dart

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,

Sample Image

like image 717
Mohamed Sadakathulla Avatar asked Apr 26 '18 13:04

Mohamed Sadakathulla


People also ask

How do you increment and decrement a single item in a ListView in flutter?

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!

How do you make an increment and decrement button in flutter?

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.


3 Answers

All you need to do is to refactor your widgets the proper way. You can refactor your Cards / items into their separate StatefulWdiget such that each increment/decrement affect only a specific item and not the whole list.

Check this example :

enter image description here

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++))
        ],
      ),
    );
  }
}
like image 118
Shady Aziza Avatar answered Oct 12 '22 22:10

Shady Aziza


If you planning to get only the UI code. here is the code to build such a beautiful button.

enter image description here

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,
                          )),
                    ],
                  ),
                ),
like image 24
MBK Avatar answered Oct 12 '22 23:10

MBK


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.

like image 2
Lasse Schuirmann Avatar answered Oct 12 '22 22:10

Lasse Schuirmann