Flutter系列十二实现购物车和提交订单页
基础工程:
一、前言
本文用flutter实现购物车和提交订单页,效果如下图:
二、使用组件
1. Card 卡片组件,扁平化风格
2. CheckBox 复选框组件,实现全选的功能
3. 数量加减插件 NumberControllerWidget
参考:flutter 自定义TextField,加减数量输入框 - 简书 (jianshu.com)
调整了下icon(加号和减号)的大小
三、完整代码
3.1 购物车页 cart.dart
-
import 'package:flutter/material.dart';
-
import 'package:flutter_play/NumberControllerWidget.dart';
-
import 'package:flutter_play/animationUtile.dart';
-
import 'package:flutter_play/checkout.dart';
-
-
/*购物车页*/
-
class CartPage extends StatefulWidget {
-
-
State<CartPage> createState() => _CartPage();
-
}
-
-
class _CartPage extends State<CartPage> {
-
-
List<bool> isChecks = [false, false, false]; //复选框状态,默认未选中
-
bool isAllSelect = false; //全选状态
-
List listData = [
-
{
-
"store": "Apple苹果旗舰店",
-
"skuName": "Apple iPhone 14 Pro (A2892) 256GB 暗紫色 支持移动联通电信5G 双卡双待手机",
-
"price": "5988",
-
"image": "https://img-blog.csdnimg.cn/c6dfd375abf1433fa3a42951cc186a2b.jpeg",
-
},
-
{
-
"store": "小米旗舰店",
-
"skuName": "Redmi K60 骁龙8 处理器 2K高光屏 6400万超清相机 5500mAh长续航",
-
"price": "2588",
-
"image": "https://img-blog.csdnimg.cn/678c0686dc694b65ad6b20693dbc35f1.jpeg",
-
},
-
{
-
"store": "耐克品牌店",
-
"skuName": "夏季新款潮流鞋",
-
"price": "1299",
-
"image": "https://img-blog.csdnimg.cn/63efe7acbac74e7ebce85e3801f948e3.jpeg",
-
},
-
];
-
-
-
Widget build(BuildContext context) {
-
return Scaffold(
-
appBar: AppBar(
-
title: const Text('购物车', style: TextStyle(fontWeight: FontWeight.w600, fontSize: 16)),
-
foregroundColor: Colors.black, //字体颜色
-
backgroundColor: const Color(0xFFFBFBFB), //顶部背景色
-
),
-
body: Column(
-
children: [
-
Expanded(
-
child: SingleChildScrollView(
-
child: Column(
-
children: [
-
skuList(),//商品列表
-
],
-
),
-
)
-
),
-
bottomFix() //底部固定栏
-
],
-
),
-
);
-
}
-
-
//商品列表
-
Container skuList(){
-
return Container(
-
width: 500,
-
height: 800,
-
padding: const EdgeInsets.only(top: 5),
-
child: ListView.builder(
-
itemCount: listData.length, //商品个数
-
itemBuilder: (context, index) {
-
return Container(
-
height: 200,
-
width: 500,
-
padding: const EdgeInsets.fromLTRB(5, 5, 5, 5), //内边距
-
margin: const EdgeInsets.fromLTRB(8, 5, 8, 0), //外边距
-
child: Card(
-
clipBehavior: Clip.hardEdge,
-
elevation: 2, //卡片海拔高度设置,立体感
-
child: InkWell(
-
splashColor: Colors.blue.withAlpha(30), //点击卡片,有蓝色透明度响应,扁平化
-
onTap: () {
-
-
}, //卡片点击
-
child: Column(
-
children: [
-
Row(
-
children: [
-
Checkbox(
-
value: isChecks[index],
-
onChanged:(value){
-
setState(() {
-
isChecks[index] = value!;
-
});
-
} ,
-
),//复选框
-
Text(listData[index]["store"], style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w600)), //店铺
-
],
-
),
-
Row(
-
children: [
-
Checkbox(
-
value: isChecks[index],
-
onChanged:(value){
-
setState(() {
-
isChecks[index] = value!;
-
});
-
} ,
-
),
-
Image.network(listData[index]["image"], width: 90, height: 90, fit: BoxFit.cover),//商品图片
-
Container(
-
width: 200,
-
height: 100,
-
padding: const EdgeInsets.fromLTRB(8, 0, 8, 0),
-
child: Column(
-
mainAxisAlignment: MainAxisAlignment.spaceBetween,
-
children: [
-
Column(
-
crossAxisAlignment: CrossAxisAlignment.start, //水平左对齐
-
children: [
-
Text(listData[index]["skuName"], style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w600), maxLines: 1, overflow: TextOverflow.ellipsis),
-
Container(
-
height: 20,
-
width: 150,
-
padding: const EdgeInsets.fromLTRB(5, 0, 5, 0),
-
decoration: BoxDecoration(
-
color: const Color(0xFFF2F2F2),
-
borderRadius: BorderRadius.circular(4), // 设置圆角
-
),
-
child: const Row(
-
mainAxisAlignment: MainAxisAlignment.spaceBetween,
-
children: [
-
Text('蓝色,64G,WLAN版', style: TextStyle(fontSize: 12, color: Colors.grey, fontWeight: FontWeight.w900)),
-
Icon(Icons.arrow_forward_ios, size: 12, color: Colors.grey)
-
],
-
)
-
), //选品
-
],
-
),
-
Row(
-
mainAxisAlignment: MainAxisAlignment.spaceBetween,
-
children: [
-
Row(
-
children: [
-
const Text('¥', style: TextStyle(color: Colors.redAccent, fontSize: 16, fontWeight: FontWeight.w600)),//金额
-
Text(listData[index]["price"], style: const TextStyle(color: Colors.redAccent, fontSize: 16, fontWeight: FontWeight.w600)),//金额
-
],
-
),
-
NumberControllerWidget(
-
addValueChanged: (num){print(num);},
-
removeValueChanged: (num){print(num);},
-
updateValueChanged: (num){},
-
)//选件组件
-
],
-
)
-
],
-
)
-
)
-
],
-
),
-
],
-
),
-
),
-
),
-
);
-
},
-
),
-
);
-
}
-
-
/*底部固定:去结算*/
-
Container bottomFix(){
-
return Container(
-
width: 500,
-
height: 50,
-
color: Colors.white,
-
padding: const EdgeInsets.all(8),
-
child: Row(
-
mainAxisAlignment: MainAxisAlignment.spaceBetween,
-
children: [
-
Row(
-
children: [
-
Checkbox(
-
value: isAllSelect,
-
onChanged:(value){
-
setState(() {
-
isAllSelect = value!;
-
//全选页面所有复选框
-
for (var i = 0; i < isChecks.length; i ) {
-
isChecks[i] = isAllSelect;
-
}
-
});
-
} ,
-
),//复选框
-
const Text(' 全选', style: TextStyle(fontSize: 14, fontWeight: FontWeight.w400)),//
-
],
-
),
-
const Row(
-
children: [
-
Text('合计金额: ', style: TextStyle(fontSize: 14, fontWeight: FontWeight.w600)),
-
Text('¥', style: TextStyle(color: Colors.redAccent, fontSize: 16, fontWeight: FontWeight.w600)),//金额
-
Text('7988', style: TextStyle(color: Colors.redAccent, fontSize: 16, fontWeight: FontWeight.w600)),//金额
-
],
-
),
-
TextButton (
-
style: ButtonStyle(
-
minimumSize: MaterialStateProperty.all(const Size(80, 30)),
-
backgroundColor: MaterialStateProperty.all(Colors.blueAccent),
-
foregroundColor: MaterialStateProperty.all<Color>(Colors.white), //字体颜色
-
shape: MaterialStateProperty.all(RoundedRectangleBorder(borderRadius: BorderRadius.circular(10))) //圆角
-
),
-
child: const Text('去结算'),
-
onPressed: () {
-
Navigator.of(context).push(showPageFromRight(CheckOutPage()));
-
},
-
),
-
]
-
),
-
);
-
}
-
-
}
3.2 提交订单页 checkout.dart
-
import 'package:flutter/material.dart';
-
import 'package:flutter_play/NumberControllerWidget.dart';
-
-
/*结算页*/
-
class CheckOutPage extends StatefulWidget {
-
-
State<CheckOutPage> createState() => _CheckOutPage();
-
}
-
-
class _CheckOutPage extends State<CheckOutPage> {
-
-
List listData = [
-
{
-
"store": "Apple苹果旗舰店",
-
"skuName": "Apple iPhone 14 Pro (A2892) 256GB 暗紫色 支持移动联通电信5G 双卡双待手机",
-
"price": "¥ 5988",
-
"image": "https://img-blog.csdnimg.cn/c6dfd375abf1433fa3a42951cc186a2b.jpeg",
-
},
-
{
-
"store": "小米旗舰店",
-
"skuName": "Redmi K60 骁龙8 处理器 2K高光屏 6400万超清相机 5500mAh长续航",
-
"price": "¥ 2588",
-
"image": "https://img-blog.csdnimg.cn/678c0686dc694b65ad6b20693dbc35f1.jpeg",
-
},
-
];
-
-
var userInfo = {
-
"nickName": "吴邪",
-
"phone": "139343254540",
-
"address": "北京市 海淀区 天秀路",
-
};
-
-
-
Widget build(BuildContext context) {
-
return Scaffold(
-
appBar: AppBar(
-
foregroundColor: Colors.black, //字体颜色
-
backgroundColor: const Color(0xFFFBFBFB), //顶部背景色
-
title: const Text('提交订单', style: TextStyle(fontWeight: FontWeight.w500, fontSize: 16)),
-
),
-
body: Column(
-
children: [
-
Expanded(
-
child: SingleChildScrollView(
-
child: Column(
-
children: [
-
addressInfo(), //地址选择
-
skuInfo(), //商品
-
priceInfo(), //金额优惠
-
],
-
),
-
),
-
),
-
bottomFix() //固定页面底部
-
],
-
)
-
);
-
}
-
-
Container addressInfo(){
-
return Container(
-
height: 90,
-
width: 500,
-
margin: const EdgeInsets.fromLTRB(8, 5, 8, 5),
-
child: Card(
-
clipBehavior: Clip.hardEdge,
-
elevation: 2,
-
child: InkWell(
-
splashColor: Colors.blue.withAlpha(30),
-
onTap: () {
-
//弹出地址管理弹窗
-
}, //卡片点击
-
child: Padding(
-
padding: const EdgeInsets.fromLTRB(10, 0, 10, 0),
-
child: Row(
-
mainAxisAlignment: MainAxisAlignment.spaceBetween,
-
children: [
-
Column(
-
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
-
crossAxisAlignment: CrossAxisAlignment.start, //水平左对齐
-
children: [
-
Text(userInfo["address"]!, style: const TextStyle(fontWeight: FontWeight.w600, fontSize: 14)),
-
Row(
-
children: [
-
Text(userInfo["nickName"]!, style: const TextStyle(fontWeight: FontWeight.w300, fontSize: 14)),
-
Padding(
-
padding: const EdgeInsets.fromLTRB(20, 0, 0, 0),
-
child: Text(userInfo["phone"]!, style: const TextStyle(fontWeight: FontWeight.w300, fontSize: 14)),
-
),
-
],
-
)
-
],
-
),
-
const Icon(Icons.arrow_forward_ios, size: 12)
-
],
-
),
-
)
-
),
-
)
-
);
-
}
-
-
//商品列表
-
SizedBox skuInfo(){
-
return SizedBox(
-
width: 500,
-
height: 370,
-
child: ListView.builder(
-
itemCount: listData.length,
-
itemBuilder: (context, index) {
-
return Container(
-
height: 180,
-
width: 500,
-
margin: const EdgeInsets.fromLTRB(10, 5, 10, 5),
-
child: Card(
-
clipBehavior: Clip.hardEdge,
-
elevation: 2,
-
child: Padding(
-
padding: const EdgeInsets.fromLTRB(10, 5, 10, 5),
-
child: Column(
-
mainAxisAlignment: MainAxisAlignment.spaceAround,
-
children: [
-
Row(
-
children: [
-
Text(listData[index]["store"], style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w600)),
-
],
-
),
-
Row(
-
children: [
-
Image.network(listData[index]["image"], width: 90, height: 90, fit: BoxFit.cover),//商品图片
-
Container(
-
width: 240,
-
height: 90,
-
padding: const EdgeInsets.fromLTRB(8, 0, 8, 0),
-
child: Column(
-
mainAxisAlignment: MainAxisAlignment.spaceBetween,
-
crossAxisAlignment: CrossAxisAlignment.start, //水平左对齐
-
children: [
-
Column(
-
crossAxisAlignment: CrossAxisAlignment.start, //水平左对齐
-
children: [
-
Text(listData[index]["skuName"], style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w600), maxLines: 1, overflow: TextOverflow.ellipsis),
-
Container(
-
height: 20,
-
width: 150,
-
padding: const EdgeInsets.fromLTRB(5, 0, 5, 0),
-
decoration: BoxDecoration(
-
color: const Color(0xFFF2F2F2),
-
borderRadius: BorderRadius.circular(4), // 设置圆角
-
),
-
child: const Row(
-
mainAxisAlignment: MainAxisAlignment.spaceBetween,
-
children: [
-
Text('蓝色,64G,WLAN版', style: TextStyle(fontSize: 12, color: Colors.grey, fontWeight: FontWeight.w900)),
-
],
-
)
-
),
-
],
-
),
-
Row(
-
mainAxisAlignment: MainAxisAlignment.spaceBetween,
-
children: [
-
Text(listData[index]["price"], style: const TextStyle(color: Colors.redAccent, fontSize: 16, fontWeight: FontWeight.w600)),//金额
-
NumberControllerWidget(
-
addValueChanged: (num){print(num);},
-
removeValueChanged: (num){print(num);},
-
updateValueChanged: (num){},
-
)//选件组件
-
],
-
)
-
],
-
)
-
)
-
],
-
),
-
],
-
),
-
)
-
-
),
-
);
-
},
-
),
-
);
-
}
-
-
Container priceInfo(){
-
return Container(
-
height: 180,
-
width: 500,
-
margin: const EdgeInsets.fromLTRB(8, 5, 8, 5),
-
child: const Card(
-
clipBehavior: Clip.hardEdge,
-
elevation: 2,
-
child: Padding(
-
padding: EdgeInsets.fromLTRB(10, 5, 10, 5),
-
child: Column(
-
mainAxisAlignment: MainAxisAlignment.spaceAround,
-
children: [
-
Row(
-
mainAxisAlignment: MainAxisAlignment.spaceBetween,
-
children: [
-
Text('商品金额', style: TextStyle(fontSize: 14, fontWeight: FontWeight.w400)),//商品名称
-
Text('¥5988', style: TextStyle(fontSize: 14, fontWeight: FontWeight.w400)),//商品名称
-
],
-
),
-
Row(
-
mainAxisAlignment: MainAxisAlignment.spaceBetween,
-
children: [
-
Text('运费', style: TextStyle(fontSize: 14, fontWeight: FontWeight.w400)),//商品名称
-
Text('¥8', style: TextStyle(fontSize: 14, fontWeight: FontWeight.w400)),//商品名称
-
],
-
),
-
Row(
-
mainAxisAlignment: MainAxisAlignment.spaceBetween,
-
children: [
-
Text('优惠券', style: TextStyle(fontSize: 14, fontWeight: FontWeight.w400)),//商品名称
-
Text('-¥20', style: TextStyle(color: Colors.redAccent, fontSize: 14, fontWeight: FontWeight.w400)),//商品名称
-
],
-
),
-
Row(
-
mainAxisAlignment: MainAxisAlignment.spaceBetween,
-
children: [
-
Text('积分', style: TextStyle(fontSize: 14, fontWeight: FontWeight.w400)),//商品名称
-
Text('-¥3', style: TextStyle(color: Colors.redAccent, fontSize: 14, fontWeight: FontWeight.w400)),//商品名称
-
],
-
)
-
],
-
),
-
)
-
)
-
);
-
}
-
-
/*底部固定:提交订单*/
-
Container bottomFix(){
-
return Container(
-
width: 500,
-
height: 50,
-
color: Colors.white,
-
child: Padding(
-
padding: const EdgeInsets.fromLTRB(10, 0, 10, 0),
-
child: Row(
-
mainAxisAlignment: MainAxisAlignment.spaceBetween,
-
children: [
-
const Row(
-
children: [
-
Text('应支付: ', style: TextStyle(fontSize: 14, fontWeight: FontWeight.w400)),//
-
Text('¥5968', style: TextStyle(color: Colors.redAccent, fontSize: 16, fontWeight: FontWeight.w600)),//商品名称
-
],
-
),
-
TextButton (
-
style: ButtonStyle(
-
minimumSize: MaterialStateProperty.all(const Size(90, 30)),
-
backgroundColor: MaterialStateProperty.all(Colors.blueAccent),
-
foregroundColor: MaterialStateProperty.all<Color>(Colors.white), //字体颜色
-
shape: MaterialStateProperty.all(RoundedRectangleBorder(borderRadius: BorderRadius.circular(10))) //圆角
-
),
-
child: const Text('提交订单'),
-
onPressed: () {
-
//跳转收银台
-
},
-
),
-
]
-
),
-
)
-
);
-
}
-
-
}
四、解决问题
4.1. 全选逻辑实现
1)如果点击非全选框,两种状态:未选择和选中,其他复选框之间是否选中不能互相影响,所以会有取值数组,保存每个复选框的状态
-
List<bool> isChecks = [false, false, false]; //其他复选框的状态,默认未选中
-
-
Checkbox(
-
value: isChecks[index],
-
onChanged:(value){
-
setState(() {
-
isChecks[index] = value!; //点击则逻辑取反,false和true直接来回转换
-
});
-
} ,
-
),//复选框
2)如果点击全选框,需要更新页面其他复选框的状态和全选框保持一致,需要循环处理,
-
bool isAllSelect = false; //全选框的状态
-
-
Checkbox(
-
value: isAllSelect,
-
onChanged:(value){
-
setState(() {
-
isAllSelect = value!; //全选框逻辑取反
-
for (var i = 0; i < isChecks.length; i ) {
-
isChecks[i] = isAllSelect; //页面所有复选框, 状态和全选框保持一致
-
}
-
});
-
} ,
-
),//复选框
本文结束
这篇好文章是转载于:学新通技术网
- 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
- 本站站名: 学新通技术网
- 本文地址: /boutique/detail/tanhfhhbag
系列文章
更多
同类精品
更多
-
photoshop保存的图片太大微信发不了怎么办
PHP中文网 06-15 -
Android 11 保存文件到外部存储,并分享文件
Luke 10-12 -
word里面弄一个表格后上面的标题会跑到下面怎么办
PHP中文网 06-20 -
《学习通》视频自动暂停处理方法
HelloWorld317 07-05 -
微信公众号没有声音提示怎么办
PHP中文网 03-31 -
photoshop扩展功能面板显示灰色怎么办
PHP中文网 06-14 -
excel下划线不显示怎么办
PHP中文网 06-23 -
excel打印预览压线压字怎么办
PHP中文网 06-22 -
怎样阻止微信小程序自动打开
PHP中文网 06-13 -
photoshop蒙版画笔没反应怎么办
PHP中文网 06-24