11

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

5 Answers5

29

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++))
        ],
      ),
    );
  }
}
Shady Aziza
  • 50,824
  • 20
  • 115
  • 113
  • While this does make the list look like the OP wants, it does create a new issue - how to get that data out later. – rmtmckenzie Apr 26 '18 at 16:48
  • 2
    that is unrelated to the question, the question did not show any code and your issue is more about state management, I do not know exactly how the OP is managing the state so there is no much I can do here. You can easily have your data list in an `InheritedWidget` and save yourself the trouble – Shady Aziza Apr 26 '18 at 16:52
  • Fair enough - it is slightly tangential to the question and I agree that the question could have been written a lot better. But if the OP is inexperienced with flutter (which seems likely given what he asked), you've just given them an answer that while technically correct will lead them *directly* into another problem. I can't think of many situations where you have something that increments, and then you never actually want to find out later what it was incremented to. – rmtmckenzie Apr 26 '18 at 17:11
  • 1
    Yes, the OP should actually open another item with the other problem since I directly answered the very specific question in this question. Otherwise, it is not worth the time imo. – Shady Aziza Apr 26 '18 at 18:50
  • Thanks for the quick reply, it helped me a lot. Yes, its my mistake. I should have provided full explanation with some codes. But with your help, i able to meet the need. Now i'll try to get the data, if any problem occurs, i'll get back to you guys. – Mohamed Sadakathulla Apr 27 '18 at 10:06
  • @aziza please explain how to extract data. I can’t ask questions. – Neeraj Yadav Jul 07 '18 at 09:42
  • @rmtmckenzie if you can also help on how to extract data, it would be very helpful. – Neeraj Yadav Jul 07 '18 at 09:43
  • This is a big a wire up and really is dependent on your code – Shady Aziza Jul 07 '18 at 10:10
  • @aziza How would you for example get the total number of items selected? In this for example it is 6. @rmtmckenzie? – Ashish Yadav Jan 08 '21 at 17:12
  • you might need this to work https://stackoverflow.com/a/54568137/5525799 – smedasn Jan 31 '21 at 15:35
  • please take a look at this question : - https://stackoverflow.com/questions/73424005/how-to-remove-item-from-cart-in-flutter-dart/73424285?noredirect=1#comment129665717_73424285 – swapnil mane Aug 20 '22 at 09:21
5

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,
                          )),
                    ],
                  ),
                ),
MBK
  • 2,589
  • 21
  • 25
2

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.

0

Add this code as a children of your Column or Row:

 itemData[index].ShouldVisible?
                             Center(
                                 child: Container(
                                   height: 30,
                                   width: 70,
                                   decoration: BoxDecoration(
                                       borderRadius: BorderRadius.circular(4),
                                       border: Border.all(color: Colors.white70)
                                   ),
                                   child: Row(
                                     mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                                     children: <Widget>[
                                       InkWell(
                                       onTap: (){
                                        setState(() {
                                          if(itemData[index].Counter <2)
                                            {
                                              itemData[index].ShouldVisible = !itemData[index].ShouldVisible;
                                            }else{
                                           itemData[index].Counter--;
                                          }

                                        });
                                       }
                                       ,child: Icon(Icons.remove,color: Colors.green,size: 18,)),
                                       Text('${itemData[index].Counter}',style: TextStyle(
                                         color: Colors.white70
                                       ),
                                       ),
                                       InkWell(
                                       onTap: (){
                                         setState(() {
                                           itemData[index].Counter++;
                                         });
                                       }
                                       ,child: Icon(Icons.add,color: Colors.green,size: 18,)),

                                     ],
                                   ),

                                 )
                             ) : Center(
                                child: Container(
                                  padding: EdgeInsets.all(5),
                                  height: 30,
                                  width: 70,
                                  decoration: BoxDecoration(
                                  borderRadius: BorderRadius.circular(4),
                                    border: Border.all(color: Colors.white70)
                                  ),
                                  child: Row(
                                    crossAxisAlignment: CrossAxisAlignment.center,
                                    mainAxisAlignment: MainAxisAlignment.center,
                                    children: <Widget>[
                                      Text('ADD',style: TextStyle(color: Colors.white70),
                                      ),
                                      InkWell(
                                        onTap: (){

                                          setState(() {
                                            itemData[index].ShouldVisible = ! itemData[index].ShouldVisible;
//                                          

                                          });
                                        }
                                          ,child: Center(child: Icon(Icons.add,color: Colors.green,size: 18,)))

                                    ],
                                  ),

                                ),
                              )

Add Counter and ShouldVisible to your DataStructure as shown below.

class ItemData{
  String Name;
  int Counter;
  bool ShouldVisible;

  ItemData({
   this.Name,
    this.Counter,
    this.ShouldVisible
});
}

List<ItemData> itemData = [
ItemData(
  Name: 'Shoes 1',
  Counter: 1,
  ShouldVisible: false
),
  ItemData(
      Name: 'Shoes 2',
      Counter: 1,
      ShouldVisible: false
  ),];
dartKnightRises
  • 815
  • 15
  • 26
0
import 'package:flutter/material.dart';


class AddButton extends StatefulWidget {
  const AddButton({Key? key}) : super(key: key);

  @override
  State<AddButton> createState() => _AddButtonState();
}

class _AddButtonState extends State<AddButton> {
  int up=0;
  

  void increment(){

    setState(() {
      if(up>=0&&up<10) {
        up++;
      }
    });
  }
  void decrement(){

    setState(() {
      if(up>1) {
        up--;
      }
    });
  }

  @override
  Widget build(BuildContext context) {


    return Row(children: [
      ElevatedButton(onPressed: (){increment();}, child: const Icon(Icons.add)),
      Padding(
        padding: const EdgeInsets.all(8.0),
        child: Container(width: 20,color: Colors.white,child: Text('$up'),),
      ),
      ElevatedButton(onPressed: (){decrement();}, child: Text("-"))
    ],);
  }
}
Md. Yeasin Sheikh
  • 54,221
  • 7
  • 29
  • 56
  • As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Sep 01 '22 at 06:35