如果我在 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
的初学者。所以我面临的问题是例如有三个产品laptop
、iphone x
和keyboard
。现在,如果我将laptop
两次放入购物车,然后在cart page
中显示两个笔记本电脑card
小部件,而我只想在该laptop qty: 2
中显示一个card
小部件。第二个问题是我在cart page
的每个card
小部件中实现了+
和-
按钮,如果我点击+
或-
按钮,那么它应该反映在qty
和total 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)=> e.title == item.title);
还是final itemIsExist = _items.where((e)=> 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<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);
内部消费者构建器
on for loop for (final item in cart._items)
在“_items”上出现错误,即 The getter '_items' isn't defined for the type 'Cart'
。
好的,你正在为类使用单独的文件,在这种情况下使用 basketItems
而不是 _items
+
和 -
按钮呢?以上是关于如果我在 Flutter 中单击多次,如何防止同一产品上出现重复的卡片小部件的主要内容,如果未能解决你的问题,请参考以下文章
当我在页面上有多个 Like 按钮时,是不是可以防止多次加载同一个 JS/CSS 文件?