63.购物车_详细页显示购物车商品数量

购物车的图标嵌套在statck组件里面

外层套了一个stack组件

数量我们需要用Provide

返回一个container来做样式

气泡效果,中间是个数字外面 是一个圆

如果想组成一个圆的形式,内边距就必须用formLRB这种形式

点击加入购物车后,数量发生变化provide/cart.dart

provide/cart.dart

效果展示:

最终代码

details_page/detail.dart

import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:provide/provide.dart';
import '../../provide/cart.dart';
import '../../provide/details_info.dart';
import '../../provide/currentIndex.dart'; class DetailsBottom extends StatelessWidget {
@override
Widget build(BuildContext context) {
var goodsInfo=Provide.value<DetailsInfoProvide>(context).goodsInfo.data.goodInfo;//当前商品的详情
var goodsId=goodsInfo.goodsId;
var goodsName=goodsInfo.goodsName;
var count=;//默认为1
var price=goodsInfo.presentPrice;
var images=goodsInfo.image1; return Container(
width: ScreenUtil().setWidth(),
color: Colors.white,
height: ScreenUtil().setHeight(),
child: Row(
children: <Widget>[
Stack(
children: <Widget>[
InkWell(
onTap: (){
Provide.value<CurrentIndexProvide>(context).changeIndex();
Navigator.pop(context);
},
child: Container(
width: ScreenUtil().setWidth(),
alignment: Alignment.center,
child: Icon(
Icons.shopping_cart,
size:,//图标没有自适应 要是设置size的大小
color: Colors.red,
),
),
),
Provide<CartProvide>(
builder: (context,child,val){
int goodsCount = Provide.value<CartProvide>(context).allGoodsCount;
return Positioned(
top: ,
right: ,
child: Container(
padding: EdgeInsets.fromLTRB(, , , ),
decoration: BoxDecoration(
color: Colors.pink,
border: Border.all(width: ,color: Colors.white),
borderRadius: BorderRadius.circular(12.0),//圆角
),
child: Text(
'${goodsCount}',
style: TextStyle(
color: Colors.white,
fontSize: ScreenUtil().setSp()
),
),
),
);
},
)
],
), InkWell(
onTap: () async{
await Provide.value<CartProvide>(context).save(goodsId, goodsName, count, price, images);
},
child: Container(
alignment: Alignment.center,
width: ScreenUtil().setWidth(),//750 - 110 再除以2 评分
height: ScreenUtil().setHeight(),
color: Colors.green,
child: Text(
'加入购物车',
style:TextStyle(color:Colors.white,fontSize: ScreenUtil().setSp()),
),
),
),
InkWell(
onTap: () async{
await Provide.value<CartProvide>(context).remove();
},
child: Container(
alignment: Alignment.center,
width: ScreenUtil().setWidth(),//750 - 110 再除以2 评分
height: ScreenUtil().setHeight(),
color: Colors.red,
child: Text(
'立即购买',
style:TextStyle(color:Colors.white,fontSize: ScreenUtil().setSp()),
),
),
)
],
),
);
}
}

provide/cart.dart

import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'dart:convert';
import '../model/cartInfo.dart'; class CartProvide with ChangeNotifier{
String cartString="[]";//声明一个变量 做持久化的存储
List<CartInfoModel> cartList=[];
double allPrice = ;//总价格
int allGoodsCount = ;//商品总数
bool isAllCheck=true;//全选 默认true //声明一个异步的方法,购物车操作放在前台不在请求后台的数据
save(goodsId,goodsName,count,price,images) async {
SharedPreferences prefs = await SharedPreferences.getInstance();
cartString= prefs.getString('cartInfo');//先从持久化中获取
var temp = cartString==null?[]:json.decode(cartString.toString());
//声明list 强制类型是Map
List<Map> tempList=(temp as List).cast();//把temp转成list
bool isHave=false;//是否已经存在了这条记录
int ival=;//foreach循环的索引
allPrice=;//总价先初始化为0
allGoodsCount=;//所有商品数量
//循环判断列表是否存在该goodsId的商品,如果有就数量+1
tempList.forEach((item){
if(item['goodsId']==goodsId){
tempList[ival]['count']=item['count']+;
cartList[ival].count++;
isHave=true;
}
if(item['isCheck']){
allPrice += (cartList[ival].price * cartList[ival].count);
allGoodsCount += cartList[ival].count;
}
ival++;
});
//没有不存在这个商品,就把商品的json数据加入的tempList中
if(!isHave){
Map<String,dynamic> newGoods={
'goodsId':goodsId,//传入进来的值
'goodsName':goodsName,
'count':count,
'price':price,
'images':images,
'isCheck':true
};
tempList.add(newGoods);
cartList.add(CartInfoModel.fromJson(newGoods)); allPrice+=(count*price);
allGoodsCount+=count;
}
cartString=json.encode(tempList).toString();//json数据转字符串
// print('字符串》》》》》》》》》》》${cartString}');
// print('字符串》》》》》》》》》》》${cartList}'); prefs.setString('cartInfo', cartString);
notifyListeners();
}
remove() async{
SharedPreferences prefs=await SharedPreferences.getInstance();
prefs.remove('cartInfo');
cartList=[];
print('清空完成----------------------');
notifyListeners();
} getCartInfo() async{
SharedPreferences prefs=await SharedPreferences.getInstance();
cartString=prefs.getString('cartInfo');//持久化中获得字符串
print('购物车持久化的数据================>'+cartString);
cartList=[];//把最终的结果先设置为空list
if(cartString==null){
cartList=[];//如果持久化内没有数据 那么就还是空的list
}else{
//声明临时的变量
List<Map> tempList=(json.decode(cartString.toString()) as List).cast();
allPrice=;//价格先初始化为0
allGoodsCount=;//数量先初始化为0
isAllCheck=true;//循环之前初始化一下
tempList.forEach((item){
if(item['isCheck']){
allPrice+=(item['count']*item['price']);
allGoodsCount +=item['count'];
}else{
isAllCheck=false;
}
cartList.add(CartInfoModel.fromJson(item));//json转成对象,加入到cartList中
}); }
notifyListeners();//通知
} //删除单个购物车商品
deleteOneGoods(String goodsId) async{
SharedPreferences prefs=await SharedPreferences.getInstance();
cartString=prefs.getString('cartInfo');
List<Map> tempList=(json.decode(cartString.toString()) as List).cast();
int tempIndex=;//定义循环的索引
int deleteIndex=;//要删除的索引
tempList.forEach((item){
if(item['goodsId']==goodsId){
deleteIndex=tempIndex;
}
tempIndex++;
});
tempList.removeAt(deleteIndex);//删除
//删除后转换成string进行持久化
cartString=json.encode(tempList).toString();//list转字符串
prefs.setString('cartInfo', cartString);
await getCartInfo();//重新获取下列表数据,因为getCartInfo方法里面有通知,这里就不再调用了
} changeCheckState(CartInfoModel cartItem) async{
SharedPreferences prefs=await SharedPreferences.getInstance();
cartString=prefs.getString('cartInfo');
List<Map> tempList=(json.decode(cartString.toString()) as List).cast();
int tempIndx=;//历史索引
int changeIndex=;//改变的索引
tempList.forEach((item){
if(item['goodsId']==cartItem.goodsId){
changeIndex=tempIndx;
}
tempIndx++;
}); tempList[changeIndex]=cartItem.toJson();//toJson就变成了Map值
cartString=json.encode(tempList).toString();
prefs.setString('cartInfo', cartString); await getCartInfo();//再次重新获取购物车的数据
} //点击全选按钮操作
changeAllCheckBtnState(bool isCheck) async{
SharedPreferences prefs=await SharedPreferences.getInstance();
cartString=prefs.getString('cartInfo');
List<Map> tempList=(json.decode(cartString.toString()) as List).cast();
List<Map> newList=[];//这里必须初始化为[]声明为一个空的值 for(var item in tempList)
{
//dart在循环的时候是不允许改变老的值的
var newItem=item;//把老的item赋值给新的item
newItem['isCheck']=isCheck;
newList.add(newItem);
} cartString=json.encode(newList).toString();
prefs.setString('cartInfo', cartString); await getCartInfo();//最后中心获取一下购物车的列表数据
} //商品数量加减
addOrReduceAction(var cartItem,String todo) async{
SharedPreferences prefs=await SharedPreferences.getInstance();
cartString=prefs.getString('cartInfo');
List<Map> tempList=(json.decode(cartString.toString()) as List).cast();
int tempIndex=;//循环的索引
int changeIndex=;//要改变的索引
tempList.forEach((item){
if(item['goodsId']==cartItem.goodsId){
changeIndex=tempIndex;
}
tempIndex++;
});
if(todo=='add'){
cartItem.count++;
}else if(cartItem.count>){
cartItem.count--;//数量只有大于1才能减减
} tempList[changeIndex]=cartItem.toJson();
cartString=json.encode(tempList).toString();
prefs.setString('cartInfo', cartString); await getCartInfo();//重新获取购物车数据
} }

Flutter实战视频-移动电商-63.购物车_详细页显示购物车商品数量的更多相关文章

  1. Flutter实战视频-移动电商-16.补充_保持页面状态

    16.补充_保持页面状态 修正一个地方: 设置了item的高度为380 横向列表为380.最终build的高度也增加了50为430. 增加了上面的高度以后,下面那个横线划掉的价格可以显示出来了. 但是 ...

  2. Flutter实战视频-移动电商-09.首页_项目结构建立和获取数据

    09.首页_项目结构建立和获取数据 在config下创建service_url.dart 用来配置我们后端接口的配置文件 一个变量存 接口地址,一个接口方法地址 所有后天请求数据的方法都放在这个文件夹 ...

  3. Flutter实战视频-移动电商-11.首页_屏幕适配方案讲解

    11.首页_屏幕适配方案讲解 国人写的屏幕适配插件: https://github.com/OpenFlutter/flutter_screenutil 最新版本是0.5.1 在pubspec.yam ...

  4. Flutter实战视频-移动电商-13.首页_广告Banner组件制作

    13.首页_广告Banner组件制作 主要是做这个小广告条. 其实就是读取一个图片做一个widget放到这里 使用stlessW快速生成 定义一个变量存放图片的url地址: 这样我们的广告条就写完了 ...

  5. Flutter实战视频-移动电商-15.首页_商品推荐模块编写

    15.首页_商品推荐模块编写 商品推荐,我们做成可以横向滚动的 分析: 上面是标题,下面是ListView,里面是一个Column, column分三层,第一是图片,第二是价格,第三是市场价格 小细节 ...

  6. Flutter实战视频-移动电商-17.首页_楼层组件的编写技巧

    17.首页_楼层组件的编写技巧 博客地址: https://jspang.com/post/FlutterShop.html#toc-b50 楼层的效果: 标题 stlessW快速生成: 接收一个St ...

  7. Flutter实战视频-移动电商-18.首页_火爆专区后台接口调试

    18.首页_火爆专区后台接口调试 楼层结束之后有个火爆专区.到地图有个上拉加载的效果 lib/config/service_url.dart 首先找到我们的接口配置文件,增加接口的配置 lib/ser ...

  8. Flutter实战视频-移动电商-19.首页_火爆专区界面布局编写

    19.首页_火爆专区界面布局编写 看一下图片的效果 一个标题栏,下面是多行两列.里面可以用column布局,外面用Warp流式布局 有得小伙伴说这里可以用网格布局,网格布局的话还是有一定的效率问题.这 ...

  9. Flutter实战视频-移动电商-20.首页_火爆专区上拉加载效果

    20.首页_火爆专区上拉加载效果 上拉加载的插件比较都.没有一个一枝独秀的 可以自定义酷炫的header和footer 一直在更新 推荐使用这个插件: https://github.com/xuelo ...

随机推荐

  1. professional cuda c programming--CUDA库简单介绍

    CUDA Libraries简单介绍   上图是CUDA 库的位置.本文简要介绍cuSPARSE.cuBLAS.cuFFT和cuRAND.之后会介绍OpenACC. cuSPARSE线性代数库,主要针 ...

  2. iperf3 测试路由器吞吐率

    mini newifi 电脑端: iperf3 -s 路由器: root@OpenWrt:/# iperf3 -c 10.10.10.3 -t 20 Connecting to host 10.10. ...

  3. less 一种 动态 样式 语言

    LESS « 一种动态样式语言 http://www.bootcss.com/p/lesscss/ 一种 动态 样式 语言. LESS 将 CSS 赋予了动态语言的特性,如 变量, 继承,运算, 函数 ...

  4. 云计算系列——HIVE1.2.1 - JDBC 服务

    前提 Hadoop 集群已经启动 Hive1.2.1 环境已经搭建 一.启动 HIVE - JDBC 服务 hiveserver2  为 hive 的 jdbc 服务,此服务默认为前台进程,需要在执行 ...

  5. bapi_goodsmvt_create-GR

    BAPI_GOODSMVT_CREATE 使用方法 * GMCODE Table T158G - - MB01 - Goods Receipts for Purchase Order * - MB31 ...

  6. 常用的Css命名方式

    常用的Css命名方式: CSS命名规范: 1.文件命名规范 全局样式:global.css: 框架布局:layout.css: 字体样式:font.css: 链接样式:link.css: 打印样式:p ...

  7. C++引用详解【转】

    本文转载自:http://www.cnblogs.com/gw811/archive/2012/10/20/2732687.html 引用:就是某一变量(目标)的一个别名,对引用的操作与对变量直接操作 ...

  8. js程序开发-2

    <h1>DOM节点操作</h1> createElement() 创建节点:返回一个元素对象; cloneNode() 克隆节点,接受一个参数deep,值为true或false ...

  9. codeforces D. Toy Sum 解题报告

    题目链接:http://codeforces.com/problemset/problem/405/D 题目意思:从 1 - 1000000 中选择 n 个数:x1,x2,...,xn,对 x1-1, ...

  10. day2-python数据类型及关系