Flutter 颤振:从StatefulWidget外部更新UI
我是一个新手,从事一个购物车项目。我不知道我问这个问题有多过分,但这就是我想要的。 我试图在购物车项目和价格发生变化时更新UI,这意味着显示从ListView(有状态小部件)到main OrderPage有状态小部件的产品总量。我知道Flutter 颤振:从StatefulWidget外部更新UI,flutter,statefulwidget,Flutter,Statefulwidget,我是一个新手,从事一个购物车项目。我不知道我问这个问题有多过分,但这就是我想要的。 我试图在购物车项目和价格发生变化时更新UI,这意味着显示从ListView(有状态小部件)到main OrderPage有状态小部件的产品总量。我知道setState()方法,但我想我应该在这里使用一些回调方法,我不太清楚 我在图中简短地解释了-见下面的img 我所做的:当用户修改购物车产品时,我已将值(价格/产品/计数)保存为常量值,我计算该值并保存为常量值,然后在主小部件(主Ui)中使用该常量变量,当我关闭并
setState()
方法,但我想我应该在这里使用一些回调方法,我不太清楚
我在图中简短地解释了-见下面的img
我所做的:当用户修改购物车产品时,我已将值(价格/产品/计数)保存为常量值,我计算该值并保存为常量值,然后在主小部件(主Ui)中使用该常量变量,当我关闭并重新打开页面时,该常量变量会更新,但在按下按钮时无法更新(产品+/-按钮)
我想做的是
按下+/-按钮时更新我的总值
这是我的全部代码:
类常数{
静态整数包计数;
静态列表;
}
类OrderPage扩展StatefulWidget{
@凌驾
_OrderPageState createState()=>\u OrderPageState();
}
类_OrderPageState扩展状态{
int数据=3;
@凌驾
小部件构建(构建上下文){
返回脚手架(
背景颜色:Colors.white,
appBar:appBar(
自动嵌入:正确,
iconTheme:IconThemeData(
颜色:Colors.black54,//在此处更改颜色
),
背景颜色:Colors.white,
立面图:1,
标题:文本(“您的订单摘要”,样式:TextStyle(颜色:Colors.black54),),
标题:对,
),
主体:容器(
儿童:
未来建设者(
生成器:(上下文,快照){
//var数据=snapshot.data;
返回
ListView.builder(
物理:ClampingScrollPhysics(),
收缩膜:对,
itemCount:数据,
itemBuilder:(构建上下文,int索引){
//购物车=数据[索引];
返回CartListView();
},
填充:边缘组。对称(水平:10.0),
滚动方向:轴垂直,
);
},
),
),
bottomNavigationBar:\u buildTotalContainer(),
);
}
小部件_buildTotalContainer(){
返回容器(
身高:220.0,
填充:仅限边缘设置(
左:10.0,
右图:10.0,
),
子:列(
儿童:[
大小盒子(
身高:10.0,
),
填充物(
填充:仅限常量边集(顶部:10),
孩子:排(
mainAxisSize:mainAxisSize.max,
mainAxisAlignment:mainAxisAlignment.spaceBetween,
儿童:[
正文(
“小计”,
样式:TextStyle(
颜色:颜色(0xFF9BA7C6),
字体大小:16.0,
fontWeight:fontWeight.bold),
),
正文(
cartConstant.packageCount.toString(),
样式:TextStyle(
颜色:颜色(0xFF6C6D6D),
字体大小:16.0,
fontWeight:fontWeight.bold),
),
],
),
),
大小盒子(
身高:15,
),
划船(
mainAxisSize:mainAxisSize.max,
mainAxisAlignment:mainAxisAlignment.spaceBetween,
儿童:[
正文(
“折扣”,
样式:TextStyle(
颜色:颜色(0xFF9BA7C6),
字体大小:16.0,
fontWeight:fontWeight.bold),
),
正文(
"0.0",
样式:TextStyle(
颜色:颜色(0xFF6C6D6D),
字体大小:16.0,
fontWeight:fontWeight.bold),
),
],
),
大小盒子(
身高:10.0,
),
分隔器(
身高:2.0,
),
大小盒子(
身高:20.0,
),
划船(
mainAxisSize:mainAxisSize.max,
mainAxisAlignment:mainAxisAlignment.spaceBetween,
儿童:[
正文(
“购物车总数”,
样式:TextStyle(
颜色:颜色(0xFF9BA7C6),
字体大小:16.0,
fontWeight:fontWeight.bold),
),
正文(
cartConstant.packageCount.toString(),
样式:TextStyle(
颜色:颜色(0xFF6C6D6D),
字体大小:16.0,
fontWeight:fontWeight.bold),
),
],
),
大小盒子(
身高:20.0,
),
手势检测器(
onTap:(){
//推送(materialPackageRoute(builder:(BuildContext context)=>SignInPage());
},
子:容器(
身高:50.0,
装饰:盒子装饰(
颜色:颜色,红色,
边界半径:边界半径。圆形(35.0),
),
儿童:中心(
子:文本(
“继续结帐”,
样式:TextStyle(
颜色:颜色,白色,
字体大小:18.0,
fontWeight:FontWe
class cartConstant{
static int packageCount;
static List<int> list;
}
class OrderPage extends StatefulWidget {
@override
_OrderPageState createState() => _OrderPageState();
}
class _OrderPageState extends State<OrderPage> {
int data = 3;
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(
automaticallyImplyLeading: true,
iconTheme: IconThemeData(
color: Colors.black54, //change your color here
),
backgroundColor: Colors.white,
elevation: 1,
title: Text("Your order Summery",style: TextStyle(color: Colors.black54),),
centerTitle: true,
),
body: Container(
child:
FutureBuilder(
builder: (context, snapshot){
// var datas = snapshot.data;
return
ListView.builder(
physics: ClampingScrollPhysics(),
shrinkWrap: true,
itemCount: data,
itemBuilder: (BuildContext context, int index){
// Cart cart = datas[index];
return CartListView();
},
padding: EdgeInsets.symmetric(horizontal: 10.0),
scrollDirection: Axis.vertical,
);
},
),
),
bottomNavigationBar: _buildTotalContainer(),
);
}
Widget _buildTotalContainer() {
return Container(
height: 220.0,
padding: EdgeInsets.only(
left: 10.0,
right: 10.0,
),
child: Column(
children: <Widget>[
SizedBox(
height: 10.0,
),
Padding(
padding: const EdgeInsets.only(top: 10),
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(
"Subtotal",
style: TextStyle(
color: Color(0xFF9BA7C6),
fontSize: 16.0,
fontWeight: FontWeight.bold),
),
Text(
cartConstant.packageCount.toString(),
style: TextStyle(
color: Color(0xFF6C6D6D),
fontSize: 16.0,
fontWeight: FontWeight.bold),
),
],
),
),
SizedBox(
height: 15,
),
Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(
"Discount",
style: TextStyle(
color: Color(0xFF9BA7C6),
fontSize: 16.0,
fontWeight: FontWeight.bold),
),
Text(
"0.0",
style: TextStyle(
color: Color(0xFF6C6D6D),
fontSize: 16.0,
fontWeight: FontWeight.bold),
),
],
),
SizedBox(
height: 10.0,
),
Divider(
height: 2.0,
),
SizedBox(
height: 20.0,
),
Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(
"Cart Total",
style: TextStyle(
color: Color(0xFF9BA7C6),
fontSize: 16.0,
fontWeight: FontWeight.bold),
),
Text(
cartConstant.packageCount.toString(),
style: TextStyle(
color: Color(0xFF6C6D6D),
fontSize: 16.0,
fontWeight: FontWeight.bold),
),
],
),
SizedBox(
height: 20.0,
),
GestureDetector(
onTap: () {
// Navigator.of(context).push(MaterialPageRoute(builder: (BuildContext context) => SignInPage()));
},
child: Container(
height: 50.0,
decoration: BoxDecoration(
color: Colors.red,
borderRadius: BorderRadius.circular(35.0),
),
child: Center(
child: Text(
"Proceed To Checkout",
style: TextStyle(
color: Colors.white,
fontSize: 18.0,
fontWeight: FontWeight.bold,
),
),
),
),
),
SizedBox(
height: 20.0,
),
],
),
);
}
}
class CartListView extends StatefulWidget {
@override
_CartListViewState createState() => _CartListViewState();
}
class _CartListViewState extends State<CartListView> {
int _counter = 1;
int getPrice(int i,int priceC){
cartConstant.packageCount = i*priceC;
return cartConstant.packageCount;
}
@override
Widget build(BuildContext context) {
return Card(
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 15.0, vertical: 15.0),
child: Row(
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
decoration: BoxDecoration(
border: Border.all(color: Color(0xFFD3D3D3), width: 2.0),
borderRadius: BorderRadius.circular(10.0),
),
child: Padding(
padding: EdgeInsets.symmetric(
horizontal: 10.0,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
InkWell(
onTap: (){
setState(() {
_counter++;
if (_counter > 20) {
_counter = 20;
}
});
},
child: Icon(Icons.add, color: Color(0xFFD3D3D3))),
Text(
"$_counter",
style: TextStyle(fontSize: 18.0, color: Colors.grey),
),
InkWell(
onTap:(){
setState(() {
_counter--;
if (_counter < 2) {
_counter = 1;
}
});
},
child: Icon(Icons.remove, color: Color(0xFFD3D3D3))),
],
),
),
),
SizedBox(
width: 20.0,
),
Container(
height: 70.0,
width: 70.0,
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage("assets/images/food.jpg"),
fit: BoxFit.cover),
borderRadius: BorderRadius.circular(35.0),
boxShadow: [
BoxShadow(
color: Colors.black54,
blurRadius: 5.0,
offset: Offset(0.0, 2.0))
]),
),
SizedBox(
width: 20.0,
),
Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
"Employee Package",
style: TextStyle(fontSize: 16.0, fontWeight: FontWeight.bold),
),
SizedBox(height: 5.0),
SizedBox(height: 5.0),
Container(
height: 25.0,
width: 120.0,
child: ListView(
scrollDirection: Axis.horizontal,
children: <Widget>[
Row(
children: <Widget>[
Text("Price",
style: TextStyle(
color: Color(0xFFD3D3D3),
fontWeight: FontWeight.bold)),
SizedBox(
width: 5.0,
),
InkWell(
onTap: () {},
child: Text(
getPrice(_counter, 2000).toString(),
style: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.red,
),
),
),
SizedBox(
width: 10.0,
),
],
),
],
),
),
],
),
Spacer(),
GestureDetector(
onTap: () {
},
child: Icon(
Icons.cancel,
color: Colors.grey,
),
),
],
),
),
);
}
}
Row(
children: <Widget>[
Text(
"Subtotal",
style: ...
),
Text(
"$subTotal",
style: ....
),
],
),
setState( (){
_counter++;
// So, the quantity is increased. Just get the price of current item and add in the sub total.
subTotal += priceC;
cartTotal = subTotal - discount;
} );
class _OrderPageState extends State<OrderPage> {
int data = 3;
void refresh() {
setState(() {});
}
...
itemBuilder: (BuildContext context, int index) {
// Cart cart = datas[index];
return CartListView(refresh);
},
...
class CartListView extends StatefulWidget {
VoidCallback callback;
CartListView(this.callback);
...
InkWell(
onTap: () {
setState(() {
_counter++;
if (_counter > 20) {
_counter = 20;
}
});
widget.callback();
},
import 'package:flutter/material.dart';
class cartConstant {
static int packageCount;
static List<int> list;
}
class OrderPage extends StatefulWidget {
@override
_OrderPageState createState() => _OrderPageState();
}
class _OrderPageState extends State<OrderPage> {
int data = 3;
void refresh() {
setState(() {});
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(
automaticallyImplyLeading: true,
iconTheme: IconThemeData(
color: Colors.black54, //change your color here
),
backgroundColor: Colors.white,
elevation: 1,
title: Text(
"Your order Summery",
style: TextStyle(color: Colors.black54),
),
centerTitle: true,
),
body: Container(
child: FutureBuilder(
builder: (context, snapshot) {
// var datas = snapshot.data;
return ListView.builder(
physics: ClampingScrollPhysics(),
shrinkWrap: true,
itemCount: data,
itemBuilder: (BuildContext context, int index) {
// Cart cart = datas[index];
return CartListView(refresh);
},
padding: EdgeInsets.symmetric(horizontal: 10.0),
scrollDirection: Axis.vertical,
);
},
),
),
bottomNavigationBar: _buildTotalContainer(),
);
}
Widget _buildTotalContainer() {
return Container(
height: 220.0,
padding: EdgeInsets.only(
left: 10.0,
right: 10.0,
),
child: Column(
children: <Widget>[
SizedBox(
height: 10.0,
),
Padding(
padding: const EdgeInsets.only(top: 10),
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(
"Subtotal",
style: TextStyle(
color: Color(0xFF9BA7C6),
fontSize: 16.0,
fontWeight: FontWeight.bold),
),
Text(
cartConstant.packageCount.toString(),
style: TextStyle(
color: Color(0xFF6C6D6D),
fontSize: 16.0,
fontWeight: FontWeight.bold),
),
],
),
),
SizedBox(
height: 15,
),
Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(
"Discount",
style: TextStyle(
color: Color(0xFF9BA7C6),
fontSize: 16.0,
fontWeight: FontWeight.bold),
),
Text(
"0.0",
style: TextStyle(
color: Color(0xFF6C6D6D),
fontSize: 16.0,
fontWeight: FontWeight.bold),
),
],
),
SizedBox(
height: 10.0,
),
Divider(
height: 2.0,
),
SizedBox(
height: 20.0,
),
Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(
"Cart Total",
style: TextStyle(
color: Color(0xFF9BA7C6),
fontSize: 16.0,
fontWeight: FontWeight.bold),
),
Text(
"8000",
style: TextStyle(
color: Color(0xFF6C6D6D),
fontSize: 16.0,
fontWeight: FontWeight.bold),
),
],
),
SizedBox(
height: 20.0,
),
GestureDetector(
onTap: () {
// Navigator.of(context).push(MaterialPageRoute(builder: (BuildContext context) => SignInPage()));
},
child: Container(
height: 50.0,
decoration: BoxDecoration(
color: Colors.red,
borderRadius: BorderRadius.circular(35.0),
),
child: Center(
child: Text(
"Proceed To Checkout",
style: TextStyle(
color: Colors.white,
fontSize: 18.0,
fontWeight: FontWeight.bold,
),
),
),
),
),
SizedBox(
height: 20.0,
),
],
),
);
}
}
class CartListView extends StatefulWidget {
VoidCallback callback;
CartListView(this.callback);
@override
_CartListViewState createState() => _CartListViewState();
}
class _CartListViewState extends State<CartListView> {
int _counter = 1;
int getPrice(int i, int priceC) {
cartConstant.packageCount = i * priceC;
return cartConstant.packageCount;
}
@override
Widget build(BuildContext context) {
return Card(
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 15.0, vertical: 15.0),
child: Row(
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
decoration: BoxDecoration(
border: Border.all(color: Color(0xFFD3D3D3), width: 2.0),
borderRadius: BorderRadius.circular(10.0),
),
child: Padding(
padding: EdgeInsets.symmetric(
horizontal: 10.0,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
InkWell(
onTap: () {
setState(() {
_counter++;
if (_counter > 20) {
_counter = 20;
}
});
widget.callback();
},
child: Icon(Icons.add, color: Color(0xFFD3D3D3))),
Text(
"$_counter",
style: TextStyle(fontSize: 18.0, color: Colors.grey),
),
InkWell(
onTap: () {
setState(() {
_counter--;
if (_counter < 2) {
_counter = 1;
}
});
widget.callback();
},
child: Icon(Icons.remove, color: Color(0xFFD3D3D3))),
],
),
),
),
SizedBox(
width: 20.0,
),
Container(
height: 70.0,
width: 70.0,
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage("assets/images/food.jpg"),
fit: BoxFit.cover),
borderRadius: BorderRadius.circular(35.0),
boxShadow: [
BoxShadow(
color: Colors.black54,
blurRadius: 5.0,
offset: Offset(0.0, 2.0))
]),
),
SizedBox(
width: 20.0,
),
Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
"Employee Package",
style: TextStyle(fontSize: 16.0, fontWeight: FontWeight.bold),
),
SizedBox(height: 5.0),
SizedBox(height: 5.0),
Container(
height: 25.0,
width: 120.0,
child: ListView(
scrollDirection: Axis.horizontal,
children: <Widget>[
Row(
children: <Widget>[
Text("Price",
style: TextStyle(
color: Color(0xFFD3D3D3),
fontWeight: FontWeight.bold)),
SizedBox(
width: 5.0,
),
InkWell(
onTap: () {},
child: Text(
getPrice(_counter, 2000).toString(),
style: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.red,
),
),
),
SizedBox(
width: 10.0,
),
],
),
],
),
),
],
),
Spacer(),
GestureDetector(
onTap: () {},
child: Icon(
Icons.cancel,
color: Colors.grey,
),
),
],
),
),
);
}
}
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: OrderPage(),
);
}
}