Shubham Vimal
Shubham Vimal

Reputation: 55

Flutter ListView.builder() item click change UI data?

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 -:

enter image description here enter image description here

Upvotes: 1

Views: 3270

Answers (3)

Jhakiz
Jhakiz

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

Guillaume Roux
Guillaume Roux

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

dm_tr
dm_tr

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

Related Questions