颤动中从孩子到父母的回调
Posted
技术标签:
【中文标题】颤动中从孩子到父母的回调【英文标题】:Callback from child to parent in flutter 【发布时间】:2021-08-04 21:33:43 【问题描述】:我正在为 e com 应用程序开发购物车页面。后端是firebase实时数据库。在购物车页面价格详细信息正在计算页面加载时。但是当用户更改购物车项目的数量时,它将更新购物车。但问题是这次不能计算价格细节。当我重新打开页面时,价格详细信息正在根据新的购物车数量计算。但是如果不重新打开页面,我怎么能做到这一点
1.这是我的 cart_page.dart 文件
//this cart is show when user select my cart From the navigation drawer
import 'package:flutter/material.dart';
import 'package:buy_app_flutter/main.dart';
import 'package:buy_app_flutter/pages/notification_page.dart';
import 'package:buy_app_flutter/pages/search_page.dart';
import 'package:buy_app_flutter/componets/cart_products.dart';
import 'BuyNowDeliveryDetailsPage.dart';
import 'HomePage.dart';
class CartPage extends StatefulWidget
@override
_CartPageState createState() => _CartPageState();
class _CartPageState extends State<CartPage>
@override
Widget build(BuildContext context)
return Scaffold(
drawer: new DrawerCodeOnly(),
appBar: new AppBar(
elevation: 0.1,
backgroundColor: Colors.orangeAccent,
title: Text("My Cart"),
actions:<Widget> [
new IconButton(icon: Icon(Icons.search,color: Colors.white,), onPressed: ()
showSearch(context: context, delegate: DataSearch());
),
new IconButton(icon: Icon(Icons.notifications,color: Colors.white,), onPressed: ()
Navigator.push(context, MaterialPageRoute(builder: (context) => new NotificationPage() ));
),
],
),
body:new Cart_products(),
bottomNavigationBar:new Container(
color: Colors.white,
child: Row(
children:<Widget> [
Expanded(child: ListTile(
title: new Text("Total:"),
subtitle:new Text("Rs 00.00") ,
)),
Expanded(
child: new MaterialButton(onPressed: ()
Navigator.push(context, MaterialPageRoute(builder: (context) => new BuyNowDeliveryDetailsActivity() ));
,
child: new Text("Check Out"),
color: Colors.orangeAccent,
)
)
],
),
) ,
);
2.这是 cart_procucts.dart 文件
import 'package:buy_app_flutter/DBModels/CartModel.dart';
import 'package:buy_app_flutter/DBModels/ProductModel.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_database/firebase_database.dart';
import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
class Cart_products extends StatefulWidget
@override
_Cart_productsState createState() => _Cart_productsState();
class _Cart_productsState extends State<Cart_products>
//firebase database reference to cart===============================
final Cartref= FirebaseDatabase.instance.reference().child("UserData").child(FirebaseAuth.instance.currentUser.uid).child("Cart");
List<CartModel> Products_on_the_cart=List();
///=============================================firebase end
bool _progressController=true;
//variables to cal total
int TotalItemPrice=0;
int SavedAmount=0;
int DeliveryPrice=0;
int TotalAmount=0;
@override
initState()
_getCartList(); //call function to get cart from firebase
super.initState();
///display the cart Items one by one===============================
@override
Widget build(BuildContext context)
if(_progressController==true) //reading database
return Center(child: new CircularProgressIndicator());
else //db read end=========
if(Products_on_the_cart.isNotEmpty)
_calTotalPrice();
//===============================================if not empty the cart
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
ListView.separated(
itemBuilder: (context, index)
return Single_cart_product(
cart_product_key: Products_on_the_cart[index].productKey,
cart_product_name: Products_on_the_cart[index].ProductTitle,
cart_prod_picture: Products_on_the_cart[index].Img,
cart_prod_price: Products_on_the_cart[index].Price,
cart_prod_cutted_price: Products_on_the_cart[index].CuttedPrice,
cart_prod_qty: Products_on_the_cart[index].qty,
cart_product_status: Products_on_the_cart[index].Status,
);
,
//end of item builder
separatorBuilder:(context,index)
return Row();
,
itemCount: Products_on_the_cart.length,
shrinkWrap: true,
),
Divider(),
Padding(
padding: const EdgeInsets.only(left: 8.0),
child: Text("PRICE DETAILS",style: TextStyle(fontWeight: FontWeight.bold,color: Colors.grey),),
),
Divider(),
///start of items total price row===========================
Padding(
padding: const EdgeInsets.only(left: 8.0,right: 8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text("price ($Products_on_the_cart.length items)",style: TextStyle(fontWeight: FontWeight.normal,color: Colors.black),),
Text("Rs $TotalItemPrice/-",style: TextStyle(fontWeight: FontWeight.normal,color: Colors.black),),
],
),
),
///end of items total price row============================
///start of delivery price row==================================
Padding(
padding: const EdgeInsets.only(left: 8.0,top: 8.0,right: 8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text("Delivery",style: TextStyle(fontWeight: FontWeight.normal,color: Colors.black),),
Text("Rs $DeliveryPrice/-",style: TextStyle(fontWeight: FontWeight.normal,color: Colors.green),),
],
),
),
///end of delivery price row============================
Divider(),
///Start of total amount row==================================
Padding(
padding: const EdgeInsets.only(left: 8.0,right: 8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text("Total Amount",style: TextStyle(fontWeight: FontWeight.bold,color: Colors.black),),
Text("Rs $TotalAmount/-",style: TextStyle(fontWeight: FontWeight.bold,color: Colors.black),),
],
),
),
///end of total amount row===========================================
Divider(),
Padding(
padding: const EdgeInsets.only(left: 8.0,right: 8.0),
child: Text("You saved Rs $SavedAmount/- on this order",style: TextStyle(fontWeight: FontWeight.normal,color: Colors.green),),
),
],
);
//end of if not empty the cart===========================================
else
return Center(child: Text("Your cart is empty !"));
///end of displaying cart items one by one====================================
_getCartList()
async
//get cart data from firebase==========
try
await Cartref.once().then((DataSnapshot snapshot)
var data = snapshot.value;
if(data==null) //if the no cart items found hide progress
setState(()
_progressController=false;
);
Products_on_the_cart.clear();
data.forEach((key,value)
async
CartModel model = new CartModel(
date: value["date"],
time: value["time"],
productKey: value["productKey"],
qty: value["qty"],
);
//use Pref(product ref) to get details from products record
try
//Product details ref and list
final Pref= FirebaseDatabase.instance.reference().child("Product");
List<ProductModel> product =List();
//====================================
await Pref.child(model.productKey).once().then((DataSnapshot snap)
// print('Product : $snap.value');
model.ProductTitle=snap.value["ProductTitle"];
model.Img=snap.value["img1"];
model.Price=snap.value["Price"];
model.DPrice=snap.value["DPrice"];
model.CuttedPrice=snap.value["CuttedPrice"];
model.Status=snap.value["Status"];
);
catch(e)
print("Error In try block for get data from real time db ");
print(e);
finally
setState(()
_progressController=false;
);
//========================================================end of get product details
setState(()
Products_on_the_cart.add(model);
);
);
);
catch(e)
print(e);
// end of get cart data from firebase
///function for calculate total price
_calTotalPrice()
TotalItemPrice=0;
DeliveryPrice=0;
TotalAmount=0;
SavedAmount=0;
Products_on_the_cart.forEach((item)
//set total item price===========
TotalItemPrice=TotalItemPrice+int.parse(item.Price)*int.parse(item.qty);
//set delivery price==========
if (item.DPrice=="FREE")
//nothing
else
if (int.parse(item.DPrice)>DeliveryPrice)
DeliveryPrice=int.parse(item.DPrice);
//set Total amount=======
TotalAmount=TotalItemPrice+DeliveryPrice;
//set saved amount
SavedAmount=SavedAmount + (int.parse(item.CuttedPrice)-int.parse(item.Price))*int.parse(item.qty);
);
/// end of calculate total price function
///from here design the cart item display ==========================================
class Single_cart_product extends StatefulWidget
final cart_product_key;
final cart_product_name;
final cart_prod_picture;
final cart_prod_price;
final cart_prod_cutted_price;
String cart_prod_qty;
final cart_product_status;
Single_cart_product(
this.cart_product_key,
this.cart_product_name,
this.cart_prod_picture,
this.cart_prod_price,
this.cart_prod_cutted_price,
this.cart_prod_qty,
this.cart_product_status,
);
@override
_Single_cart_productState createState() => _Single_cart_productState();
class _Single_cart_productState extends State<Single_cart_product>
///==========================start of Cart Item Display Design==================================================================
@override
Widget build(BuildContext context)
var cartQty=int.parse(widget.cart_prod_qty);
return Card(
child: Column(
children: [
ListTile(
///===============START LEADING SECTION ===============================
leading: FadeInImage.assetNetwork(
placeholder: 'assets/close_box.png',
image:widget.cart_prod_picture,
height: 80.0,
width: 80.0,
fit: BoxFit.contain,
),
///=======END OF LEADING SECTION=======================================
/// =========== TITLE SECTION =========================================
title: new Text(widget.cart_product_name),
///====END OF TITLE SECTION============================================
///========== SUBTITLE SECTION ==================================
subtitle: new Column(
children:<Widget> [
//Row inside the column
new Row(
children: <Widget> [
// =============this section is for the Product price =====
new Container(
alignment: Alignment.topLeft,
child: new Text("\Rs.$widget.cart_prod_price",
style: TextStyle(
fontSize:16.0,
fontWeight: FontWeight.bold,
color: Colors.black
),
),
),
SizedBox(width: 4,),
//==========this section is for the cutted price of the product=========
Padding(
padding: const EdgeInsets.all(5.0),
child: new Text("\Rs.$widget.cart_prod_cutted_price",
style: TextStyle(
fontSize:16.0,
fontWeight: FontWeight.normal,
decoration: TextDecoration.lineThrough,
color: Colors.grey
),
),
),
//end of cutted price of the product
],
),
],
),
///=====END OF SUBTITLE SECTION============================================
///======START OF TRAILING SECTION==========================================
trailing:
Column(
children:
<Widget>[
Expanded(child: new IconButton(
padding: const EdgeInsets.all(0.0),
icon: Icon(Icons.arrow_drop_up), onPressed: ()
cartQty++;
print(cartQty);
_updateCartQty(widget.cart_product_key,cartQty.toString()); //call to update cart qty
setState(()
widget.cart_prod_qty=cartQty.toString();
);
)),
Padding(
padding: const EdgeInsets.all(0.0),
child: new Text(cartQty.toString()),
),
Expanded(child: new IconButton(
padding: const EdgeInsets.all(0.0),
icon: Icon(Icons.arrow_drop_down), onPressed: ()
if(cartQty>1)
cartQty--;
print(cartQty);
_updateCartQty(widget.cart_product_key,cartQty.toString()); //call to update cart qty
setState(()
widget.cart_prod_qty=cartQty.toString();
);
)),
],
),
///==END OF TRAILING======================================================================
),
//REMOVE BTN AND STATUS
Row(
children: [
new IconButton(
icon: Icon(Icons.delete),
color:Colors.red ,
onPressed: ()),
Padding(
padding: const EdgeInsets.all(4.0),
child: new Text(widget.cart_product_status,style: TextStyle(color: Colors.orangeAccent)),
),
],
)
//END OF REMOVE BTN SND STATUS
],
),
);
///==========================end of Cart Item Display Design==================================================================
/// function for update cart qty
_updateCartQty(String Pkey,String Qty)
try
final Cartref = FirebaseDatabase.instance.reference()
.child("UserData")
.child(FirebaseAuth.instance.currentUser.uid)
.child("Cart");
Cartref.child(Pkey).child("qty").set(Qty);
catch(Ex)
Fluttertoast.showToast(
msg: Ex.message,
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.BOTTOM,
timeInSecForiosWeb: 1,
backgroundColor: Colors.red,
textColor: Colors.white,
fontSize: 16.0);
3.之后我需要在购物车页面底部查看计算出的总金额
【问题讨论】:
***.com/questions/67312142/… 【参考方案1】:更新Cart_products
类中的产品数量值:
您需要在Single_cart_product
类中创建一个变量final ValueChanged<int> onProdQty;
,然后在数量值更改的地方使用像widget.onProdQty?.call(here Pass the new quantity value)
这样的回调。最后一步是在类Cart_products
中调用Single_cart_product()
将其添加到参数onProdQty: (value) => setState(() Products_on_the_cart[index].qty = value; ),
中。通过在调用回调时执行此操作,setstate 将在 Cart_products
类中运行,并且无论在何处使用 Products_on_the_cart[index].qty
,它都会得到更新。
更新CartPage
类中的产品数量值:
注意:我不确定这些步骤是否能正常工作,因为我对您的项目的信息有限。但你肯定会学会如何使用回调传递数据:
按照在Cart_products
中更新产品数量值的步骤进行操作
上课,然后继续。
在Cart_products
类中添加final ValueChanged<int> onProdQty;
和
然后更改 Single_cart_product()
类中的参数 Cart_products
像这样:
Single_cart_product(onProdQty: (value) => setState(()
Products_on_the_cart[index].qty = value;
widget.onProdQty?.call(value); //add this
),)
然后添加List<CartModel> Products_on_the_cart=List();
在
在cart_page.dart 中的_CartPageState
类以及最后在body: Cart_products()
中进行这些更改:
Cart_products(onProdQty: (value) => setState(()
Products_on_the_cart[index].qty = value;
),)
现在在底部导航栏中使用Products_on_the_cart[index].qty
。
如果您有任何疑问,请告诉我。
【讨论】:
非常感谢。这是工作。 !云你请给我一个建议,将总金额发送到 cart_page.dart 中的底部导航栏 我很高兴它对你有用。至于建议,我很快会在答案中分享一个简单的项目,这将帮助您更加熟悉回调。但截至目前,我已经更新了bottomNavigationBar
的答案。不幸的是,我不能保证它会起作用,因为我对您的项目的信息有限。但我相信它会给你这个想法。以上是关于颤动中从孩子到父母的回调的主要内容,如果未能解决你的问题,请参考以下文章
指定的孩子已经有一个父母。您必须首先在孩子的父母上调用 removeView()。 (C#)
Fragments - 指定的孩子已经有一个父母。您必须先在孩子的父母上调用 removeView()