如果我在 Flutter 中单击多次,如何防止同一产品上出现重复的卡片小部件

Posted

技术标签:

【中文标题】如果我在 Flutter 中单击多次,如何防止同一产品上出现重复的卡片小部件【英文标题】:How to prevent duplicate card widget on same product if i click more than one time in 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;
  

【问题讨论】:

【参考方案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 +- 按钮呢?

以上是关于如果我在 Flutter 中单击多次,如何防止同一产品上出现重复的卡片小部件的主要内容,如果未能解决你的问题,请参考以下文章

如何防止在 PHP 中多次单击时提交多个表单

如何在单击同一tr的td内的按钮时防止单击tr [重复]

当我在页面上有多个 Like 按钮时,是不是可以防止多次加载同一个 JS/CSS 文件?

如何防止部分视图中的脚本多次加载并在同一页面中多次使用部分时导致错误

防止多次点击同一个 UIButton

我如何调整这个选择语句以防止它多次从同一个表中选择?