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

Flutter实战视频-移动电商-63.购物车_详细页显示购物车商品数量_初始化

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

Flutter实战视频-移动电商-63.购物车_详细页显示购物车商品数量_持久化_02

外层套了一个stack组件

Flutter实战视频-移动电商-63.购物车_详细页显示购物车商品数量_持久化_03

数量我们需要用Provide

Flutter实战视频-移动电商-63.购物车_详细页显示购物车商品数量_持久化_04

 

Flutter实战视频-移动电商-63.购物车_详细页显示购物车商品数量_持久化_05

返回一个container来做样式

Flutter实战视频-移动电商-63.购物车_详细页显示购物车商品数量_初始化_06

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

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

Flutter实战视频-移动电商-63.购物车_详细页显示购物车商品数量_flutter_07

 

Flutter实战视频-移动电商-63.购物车_详细页显示购物车商品数量_json_08

 

Flutter实战视频-移动电商-63.购物车_详细页显示购物车商品数量_持久化_09

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

provide/cart.dart

Flutter实战视频-移动电商-63.购物车_详细页显示购物车商品数量_持久化_10

 

效果展示:

Flutter实战视频-移动电商-63.购物车_详细页显示购物车商品数量_初始化_11

 

最终代码

 

details_page/detail.dart

Flutter实战视频-移动电商-63.购物车_详细页显示购物车商品数量_初始化_12Flutter实战视频-移动电商-63.购物车_详细页显示购物车商品数量_flutter_13
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;//默认为1
    var price=goodsInfo.presentPrice;
    var images=goodsInfo.image1;


    return Container(
      width: ScreenUtil().setWidth(750),
      color: Colors.white,
      height: ScreenUtil().setHeight(80),
      child: Row(
        children: <Widget>[
          Stack(
            children: <Widget>[
              InkWell(
                onTap: (){
                  Provide.value<CurrentIndexProvide>(context).changeIndex(2);
                  Navigator.pop(context);
                },
                child: Container(
                  width: ScreenUtil().setWidth(110),
                  alignment: Alignment.center,
                  child: Icon(
                    Icons.shopping_cart,
                    size:35,//图标没有自适应 要是设置size的大小
                    color: Colors.red,
                  ),
                ),            
              ),
              Provide<CartProvide>(
                builder: (context,child,val){
                  int goodsCount = Provide.value<CartProvide>(context).allGoodsCount;
                  return Positioned(
                    top: 0,
                    right: 10,
                    child: Container(
                      padding: EdgeInsets.fromLTRB(6, 3, 6, 3),
                      decoration: BoxDecoration(
                        color: Colors.pink,
                        border: Border.all(width: 2,color: Colors.white),
                        borderRadius: BorderRadius.circular(12.0),//圆角
                      ),
                      child: Text(
                        '${goodsCount}',
                        style: TextStyle(
                          color: Colors.white,
                          fontSize: ScreenUtil().setSp(22)
                        ),
                      ),
                    ),
                  );
                },
              )
            ],
          ),
          
          InkWell(
            onTap: () async{
              await Provide.value<CartProvide>(context).save(goodsId, goodsName, count, price, images);
            },
            child: Container(
              alignment: Alignment.center,
              width: ScreenUtil().setWidth(320),//750 - 110 再除以2 评分
              height: ScreenUtil().setHeight(80),
              color: Colors.green,
              child: Text(
                '加入购物车',
                style:TextStyle(color:Colors.white,fontSize: ScreenUtil().setSp(28)),
              ),
            ),
          ),
          InkWell(
            onTap: () async{
              await Provide.value<CartProvide>(context).remove();
            },
            child: Container(
              alignment: Alignment.center,
              width: ScreenUtil().setWidth(320),//750 - 110 再除以2 评分
              height: ScreenUtil().setHeight(80),
              color: Colors.red,
              child: Text(
                '立即购买',
                style:TextStyle(color:Colors.white,fontSize: ScreenUtil().setSp(28)),
              ),
            ),
          )
        ],
      ),
    );
  }
}
View Code

 

 

provide/cart.dart

Flutter实战视频-移动电商-63.购物车_详细页显示购物车商品数量_初始化_12Flutter实战视频-移动电商-63.购物车_详细页显示购物车商品数量_flutter_13
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 = 0;//总价格
  int allGoodsCount = 0;//商品总数
  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=0;//foreach循环的索引
    allPrice=0;//总价先初始化为0
    allGoodsCount=0;//所有商品数量
    //循环判断列表是否存在该goodsId的商品,如果有就数量+1
    tempList.forEach((item){
      if(item['goodsId']==goodsId){
        tempList[ival]['count']=item['count']+1;
        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;//价格先初始化为0
      allGoodsCount=0;//数量先初始化为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=0;//定义循环的索引
    int deleteIndex=0;//要删除的索引
    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=0;//历史索引
    int changeIndex=0;//改变的索引
    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=0;//循环的索引
    int changeIndex=0;//要改变的索引
    tempList.forEach((item){
      if(item['goodsId']==cartItem.goodsId){
        changeIndex=tempIndex;
      }
      tempIndex++;
    });
    if(todo=='add'){
      cartItem.count++;
    }else if(cartItem.count>1){
      cartItem.count--;//数量只有大于1才能减减
    }

    tempList[changeIndex]=cartItem.toJson();
    cartString=json.encode(tempList).toString();
    prefs.setString('cartInfo', cartString);

    await getCartInfo();//重新获取购物车数据
  }

}
View Code