【问题标题】:How to prevent duplicate card widget on same product if i click more than one time in Flutter如果我在 Flutter 中单击多次,如何防止同一产品上出现重复的卡片小部件
【发布时间】:2022-01-17 21:05:44
【问题描述】:

我使用provider 库状态管理来添加到购物车,基本上我是provider 的初学者。所以我面临的问题是例如有三个产品laptopiphone xkeyboard。现在,如果我将laptop 两次放入购物车,然后在cart page 中显示两个笔记本电脑card 小部件,而我只想在该laptop qty: 2 中显示一个card 小部件。第二个问题是我在cart page 的每个card 小部件中实现了+- 按钮,如果我点击+- 按钮,那么它应该反映在qtytotal price。如果你能帮助我解决这个问题,真的很感激。

main.dart

void main() {
  runApp(ChangeNotifierProvider(
    create: (context) => Cart(),
    child: MyApp(),
  ));
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: HomePage(),
      debugShowCheckedModeBanner: false,
    );
  }
}

class HomePage extends StatefulWidget {
  @override
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  final List<Item> items = [
    Item(title: 'laptop ', price: 500.0),
    Item(title: 'iphone x ', price: 400.0),
    Item(title: 'keyboard ', price: 40.0),
  ];
  @override
  Widget build(BuildContext context) {
    return Consumer<Cart>(builder: (context, cart, child) {
      return Scaffold(
        appBar: AppBar(
          title: Text('Shopping cart'),
          actions: <Widget>[
            Padding(
              padding: EdgeInsets.all(8.0),
              child: Row(
                children: <Widget>[
                  IconButton(
                    icon: Icon(
                      Icons.shopping_cart,
                      color: Colors.white,
                    ),
                    onPressed: () {
                      Navigator.of(context).push(MaterialPageRoute(
                          builder: (context) => CheckoutPage()));
                    },
                  ),
                  Text(cart.count.toString())
                ],
              ),
            )
          ],
          centerTitle: true,
        ),
        body: ListView.builder(
          itemCount: items.length,
          itemBuilder: (context, index) {
            return ListTile(
              title: Text(items[index].title),
              subtitle: Text(items[index].price.toString()),
              trailing: Icon(Icons.add),
              onTap: () {
                cart.add(items[index]);
              },
            );
          },
        ),
      );
    });
  }
}

CheckoutPage.dart

class CheckoutPage extends StatefulWidget {
  @override
  _CheckoutPageState createState() => _CheckoutPageState();
}

class _CheckoutPageState extends State<CheckoutPage> {
  @override
  Widget build(BuildContext context) {
    return Consumer<Cart>(
      builder: (context, cart, child) {
        return Scaffold(
            appBar: AppBar(
              title: Text('Checkout Page [\$ ${cart.totalPrice}]'),
              actions: [
                TextButton(
                    onPressed: () {
                      print(cart.totalPrice);
                    },
                    child: Text('Check'))
              ],
            ),
            body: cart.basketItems.length == 0
                ? Text('no items in your cart')
                : ListView.builder(
                    itemCount: cart.basketItems.length,
                    itemBuilder: (context, index) {
                      return Card(
                        child: ListTile(
                          title: Text(cart.basketItems[index].title),
                          subtitle: Row(
                            children: [
                              TextButton(onPressed: () {}, child: Text('+')),
                              Text(cart.basketItems[index].qty.toString()),
                              TextButton(onPressed: () {}, child: Text('-')),
                            ],
                          ),
                          trailing: IconButton(
                            icon: Icon(Icons.delete),
                            onPressed: () {
                              cart.remove(cart.basketItems[index]);
                            },
                          ),
                        ),
                      );
                    },
                  ));
      },
    );
  }
}

Item.dart

class Item {
  String title;
  double price;
  Item({this.title, this.price});
}

购物车.dart

class Cart extends ChangeNotifier {
  List<Item> _items = [];
  double _totalPrice = 0.0;

  void add(Item item) {
    _items.add(item);
    _totalPrice += item.price;
    notifyListeners();
  }

  void remove(Item item) {
    _totalPrice -= item.price;
    _items.remove(item);
    notifyListeners();
  }

  int get count {
    return _items.length;
  }

  double get totalPrice {
    return _totalPrice;
  }

  List<Item> get basketItems {
    return _items;
  }
}

【问题讨论】:

    标签: flutter dart provider


    【解决方案1】:

    嗯,在添加项目之前尝试添加一个特定的功能,它将像这样查找重复的项目

    例如在里面添加

    在 item.dart 上的类上添加数量,以便在每个添加项目中,您应该将默认数量设置为一个,然后在下面进行。

    class Item {
      String title;
      double price;
      int qty;
      Item({this.title, this.price,this.qty});
    }
    
    void add(Item item) {
      final itemIsExist  = _items.where((e)=> e.title == item.title);
        if(itemIsExist.isNotEmpty){
       // if item exist and you want to add +1 on qty
       final addQty = _items.firstWhere((e)=> e.title == item.title);
       addQty.qty= addQty.qty+1;
       // do your thing here to calculate again the total
    }else{
     _items.add(item);
        _totalPrice += item.price;
        notifyListeners();
    }
      }
    

    【讨论】:

    • final itemIsExist = items.where((e)=&gt; e.title == item.title); 还是final itemIsExist = _items.where((e)=&gt; e.title == item.title); 因为我在items 上遇到错误。
    • 我想检查是否存在然后制作数量 2。如何做到这一点?
    • @MohammedNabil 尝试上面我编辑了一些
    • 如果我在单个产品上单击两次,我会收到错误The method '+' was called on null. Receiver: null Tried calling: +(1)
    • 嗯,尝试将 +1 更改为 ++,这样它将是 addQty.qty++
    【解决方案2】:

    我建议在基类上创建另一个变量并为模型扩展它,但现在让我们按照你的方式。

    我们可以创建一个map 来迭代_CheckoutPageState 上的项目并创建一个Set,但是我们需要计算项目数量,

    在这种情况下,我们可以借助 map 将其放在 Consumer builder 下方,然后返回 Scaffold

    Map<String, int> itemsMap = {};
    
    for (final item in cart._items) {
      if (!itemsMap.containsKey(item.title)) {
        itemsMap.putIfAbsent(item.title, () => 1);
      } else {
        itemsMap.update(item.title, (value) => itemsMap[item.title]! + 1);
      }
    }
    

    用途会是这样的

    itemBuilder: (context, index) {
      final keys = itemsMap.keys.toList();
      final count = itemsMap.values.toList();
      return Card(
        child: ListTile(
          title: Text(keys[index].toString()),
          subtitle: Row(
            children: [
              TextButton(onPressed: () {}, child: Text('+')),
              Text(count[index].toString()),
              TextButton(onPressed: () {}, child: Text('-')),
            ],
          ),
    

    状态类

    
    
    class _CheckoutPageState extends State<CheckoutPage> {
      @override
      Widget build(BuildContext context) {
        return Consumer<Cart>(
          builder: (context, cart, child) {
            Map<String, int> itemsMap = {};
    
            for (final item in cart.basketItems) {
              if (!itemsMap.containsKey(item.title)) {
                itemsMap.putIfAbsent(item.title, () => 1);
              } else {
                itemsMap.update(item.title, (value) => itemsMap[item.title]! + 1);
              }
            }
            return Scaffold(
                appBar: AppBar(
                  title: Text('Checkout Page [\$ ${cart.totalPrice}]'),
                  actions: [
                    TextButton(
                        onPressed: () {
                          print(cart.totalPrice);
                        },
                        child: Text('Check'))
                  ],
                ),
                body: cart.basketItems.length == 0
                    ? Text('no items in your cart')
                    : ListView.builder(
                        itemCount: itemsMap.length,
                        itemBuilder: (context, index) {
                          final keys = itemsMap.keys.toList();
                          final count = itemsMap.values.toList();
                          return Card(
                            child: ListTile(
                              title: Text(keys[index].toString()),
                              subtitle: Row(
                                children: [
                                  TextButton(
                                      onPressed: () {
                                        cart.add(
                                          Item(
                                            title: keys[index].toString(),
                                            price: keys[index].trim() == "laptop"
                                                ? 500
                                                : keys[index].trim() == "iphone x"
                                                    ? 400
                                                    : 40,
                                          ),
                                        );
                                      },
                                      child: Text('+')),
                                  Text(count[index].toString()),
                                  TextButton(
                                      onPressed: () {
                                        cart.remove(Item(
                                          title: keys[index].toString(),
                                          price: keys[index].trim() == "laptop"
                                              ? 500
                                              : keys[index].trim() == "iphone x"
                                                  ? 400
                                                  : 40,
                                        ));
                                      },
                                      child: Text('-')),
                                ],
                              ),
                              trailing: IconButton(
                                icon: Icon(Icons.delete),
                                onPressed: () {
                                  cart.remove(cart.basketItems[
                                      index]); // remove match all on remove method
                                },
                              ),
                            ),
                          );
                        },
                      ));
          },
        );
      }
    }
    
    

    【讨论】:

    • 我把这行代码放在_CheckoutPageState 哪里? Map&lt;String, int&gt; itemsMap = {}; for (final item in cart._items) { if (!itemsMap.containsKey(item.title)) { itemsMap.putIfAbsent(item.title, () =&gt; 1); } else { itemsMap.update(item.title, (value) =&gt; itemsMap[item.title]! + 1); } }
    • 内部消费者构建器
    • on for loop for (final item in cart._items) 在“_items”上出现错误,即 The getter '_items' isn't defined for the type 'Cart'
    • 好的,你正在为类使用单独的文件,在这种情况下使用 basketItems 而不是 _items
    • +- 按钮呢?
    猜你喜欢
    • 1970-01-01
    • 2019-03-10
    • 2020-08-22
    • 1970-01-01
    • 2022-07-20
    • 1970-01-01
    • 1970-01-01
    • 2022-09-22
    • 2018-07-27
    相关资源
    最近更新 更多