仿饿了么添加购物车效果

640?wx_fmt=png


今日科技快讯


近日大量商家前往拼多多上海总部维权,双方发生肢体冲突一事,拼多多方面对此回应称,“拼多多打假的决心不变,站消费者的立场不变”。声明中,拼多多称现场聚集的14名问题商家中,7家存在售假情况,6家存在商品描述不符情况,1家存在虚假发货情况。拼多多按相应情形,分别对问题商家作出扣除“消费者赔偿金”的处理。


作者简介


大家早上好,明天就是端午小长假啦,再加上四年一度的世界杯也在今天开赛了,真是双节同至,双喜临门。假期里面大家都可以好好休息一下,看看球赛什么的,提前祝大家节日快乐,我们节后再见。

本篇来自 Master_文 的投稿,分享了他实现饿了么购物车的过程,希望对大家有所帮助。

Master_文  的博客地址:

https://www.jianshu.com/u/0b51eed8edba


前言



最近有一个需求,要实现一个像饿了么添加购物车的效果,下面是效果图

640?wx_fmt=gif

主要有以下几点
  • 沉浸式状态栏

  • 上下滑动的动画

  • 添加减少的动画

  • 贝塞尔曲线动画

  • 底部购物车弹窗动画

  • 购物车缓存


沉浸式状态栏


沉浸式状态栏网上有很多,通常都是放 v19 和 v21 的包,然后在最外层ViewGroup设置 fitsSystemWindows = "true" ,这种方式我不太推荐,因为你每次都要写 fitsSystemWindows  这个属性,可能你会说我抽取出来不就好了,ok,那有时候要的效果不是我想要的,就比如我图上的效果,那怎么办呢,其实,有时候,你只需要一点小小的bang助!!!,几行代码的事

values

<style name="AppTheme.TranslucentTheme" parent="Theme.AppCompat.Light.NoActionBar"/>

values-v19

<style name="TranslucentTheme" parent="Theme.AppCompat.Light.NoActionBar">
   <item name="android:windowTranslucentStatus">true</item>
   <item name="android:windowTranslucentNavigation">true</item>
</style>

values-v21

<style name="TranslucentTheme" parent="Theme.AppCompat.Light.NoActionBar">
       <item name="android:windowTranslucentStatus">false</item>
       <item name="android:windowTranslucentNavigation">true</item>
       <!--Android 5.x开始需要把颜色设置透明,否则导航栏会呈现系统默认的浅灰色-->
       <item name="android:statusBarColor">@android:color/transparent</item>
</style>

重头戏来了,以 ToolBar 为例,动态设置 ToolBar 的高度,并且设置一个 padding,top 为状态栏的高度,搞定收工!

activity
    @Override
   protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
           setHeight(mToolbar);
       }
   }

   public void setHeight(View view) {
       // 获取actionbar的高度
       TypedArray actionbarSizeTypedArray = obtainStyledAttributes(new int[]{
               android.R.attr.actionBarSize
       });
       float height = actionbarSizeTypedArray.getDimension(0, 0);
       // ToolBar的top值
       ViewGroup.MarginLayoutParams lp = (ViewGroup.MarginLayoutParams) view.getLayoutParams();
       double statusBarHeight = getStatusBarHeight(this);
       lp.height = (int) (statusBarHeight + height);
       view.setPadding(0,(int) statusBarHeight,0, 0);
       mToolbar.setLayoutParams(lp);
   }

   private double getStatusBarHeight(Context context) {
       int result = 0;
       int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen",
               "android");
       if (resourceId > 0) {
           result = context.getResources().getDimensionPixelSize(resourceId);
       }
       return result;
   }
xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.Toolbar
   xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:app="http://schemas.android.com/apk/res-auto"
   xmlns:tools="http://schemas.android.com/tools"
   android:id="@+id/toolbar"
   android:layout_width="match_parent"
   android:layout_height="?attr/actionBarSize"
   app:contentInsetStart="0dp"
   app:layout_collapseMode="pin">

   <FrameLayout
       android:layout_gravity="bottom"
       android:layout_width="match_parent"
       android:layout_height="?attr/actionBarSize">

       <ImageView
           android:id="@+id/iv_back"
           android:layout_width="44dp"
           android:layout_height="44dp"
           android:layout_gravity="center_vertical"
           android:padding="14dp"
           android:src="@mipmap/icon_back"/>

       <TextView
           android:id="@+id/tv_title"
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:layout_gravity="center"
           android:textColor="#ffffff"
           android:textSize="18sp"
           tools:text="Title"/>
   </FrameLayout>
</android.support.v7.widget.Toolbar>
下面是效果图

640?wx_fmt=gif


上下滑动动画


没什么好说的,design包下的协调式布局(CoordinatorLayout),可以很好地实现这种效果,监听AppBarLayout的状态,打开的时候,隐藏标题,关闭的时候.显示标题,同时监听高度变化做透明度动画效果

XML布局
<android.support.design.widget.CoordinatorLayout
   xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:app="http://schemas.android.com/apk/res-auto"
   xmlns:tools="http://schemas.android.com/tools"
   android:id="@+id/coordinatorLayout"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   android:orientation="vertical"
   tools:context=".ui.activity.ShoppingGoodsActivity">


   <android.support.design.widget.AppBarLayout
       android:id="@+id/appBarLayout"
       android:layout_width="match_parent"
       android:layout_height="200dp"
       android:orientation="vertical">


       <android.support.design.widget.CollapsingToolbarLayout
           android:layout_width="match_parent"
           android:layout_height="match_parent"
           android:background="@mipmap/icon_shopping_goods_bg"
           app:expandedTitleMarginStart="?attr/actionBarSize"
           app:layout_scrollFlags="scroll|exitUntilCollapsed">


           <RelativeLayout
               android:id="@+id/rl_header"
               android:layout_width="match_parent"
               android:layout_height="wrap_content"
               android:layout_gravity="bottom">


               <ImageView
                   android:id="@+id/iv_goods_icon"
                   android:layout_width="80dp"
                   android:layout_height="80dp"
                   android:layout_marginBottom="15dp"
                   android:layout_marginLeft="16dp"
                   android:src="@mipmap/ic_launcher"/>


               <TextView
                   android:id="@+id/tv_goods_title"
                   android:layout_width="wrap_content"
                   android:layout_height="wrap_content"
                   android:layout_marginLeft="115dp"
                   android:text="巴比馒头(四季店)"
                   android:textColor="#FFFFFF"
                   android:textSize="18sp"/>


               <TextView
                   android:id="@+id/tv_goods_count"
                   android:layout_width="wrap_content"
                   android:layout_height="wrap_content"
                   android:layout_alignLeft="@id/tv_goods_title"
                   android:layout_below="@id/tv_goods_title"
                   android:layout_marginTop="1dp"
                   android:text="月销2390单"
                   android:textColor="#FFFFFF"
                   android:textSize="12sp"/>


               <TextView
                   android:id="@+id/tv_goods_address"
                   android:layout_width="wrap_content"
                   android:layout_height="wrap_content"
                   android:layout_alignLeft="@id/tv_goods_title"
                   android:layout_below="@id/tv_goods_count"
                   android:layout_marginTop="3dp"
                   android:text="上海市浦东新区东二环路与新海大道"
                   android:textColor="#FFFFFF"
                   android:textSize="12sp"/>


               <TextView
                   android:layout_width="wrap_content"
                   android:layout_height="wrap_content"
                   android:layout_alignLeft="@id/tv_goods_title"
                   android:layout_below="@id/tv_goods_address"
                   android:text="021-87689283"
                   android:textColor="#FFFFFF"
                   android:textSize="12sp"/>


               <LinearLayout
                   android:id="@+id/ll_discount_coupon"
                   android:layout_width="match_parent"
                   android:layout_height="44dp"
                   android:layout_below="@id/iv_goods_icon"
                   android:background="#FFFFFF"
                   android:gravity="center_vertical"
                   android:orientation="horizontal">


                   <ImageView
                       android:id="@+id/iv_discount_coupon"
                       android:layout_width="17dp"
                       android:layout_height="17dp"
                       android:layout_marginLeft="16dp"
                       android:src="@mipmap/icon_discount_coupon"/>


                   <TextView
                       android:layout_width="wrap_content"
                       android:layout_height="wrap_content"
                       android:layout_marginLeft="6dp"
                       android:text="5元优惠券"
                       android:textColor="#333333"
                       android:textSize="12sp"/>


                   <Space
                       android:layout_width="0dp"
                       android:layout_height="0dp"
                       android:layout_weight="1"/>


                   <TextView
                       android:id="@+id/tv_goods_get"
                       android:layout_width="wrap_content"
                       android:layout_height="match_parent"
                       android:layout_marginRight="19dp"
                       android:gravity="center"
                       android:text="点击领取"
                       android:textColor="#BCBCBC"
                       android:textSize="12sp"/>

               </LinearLayout>

               <View
                   android:layout_width="match_parent"
                   android:layout_height="9dp"
                   android:layout_below="@id/ll_discount_coupon"
                   android:background="#EFEFEF"/>

           </RelativeLayout>

           <include layout="@layout/layout_toolbar"/>
       </android.support.design.widget.CollapsingToolbarLayout>
   </android.support.design.widget.AppBarLayout>

   <android.support.v7.widget.RecyclerView
       android:id="@+id/rv_goods"
       android:layout_width="match_parent"
       android:layout_height="match_parent"
       android:layout_marginBottom="50dp"
       android:background="#ffffff"
       app:layout_behavior="@string/appbar_scrolling_view_behavior"/>


   <include
       android:id="@+id/layout_shopping_cart"
       layout="@layout/layout_shopping_cart"/>

</android.support.design.widget.CoordinatorLayout>
AppBarStateChangeListener
public abstract class AppBarStateChangeListener implements AppBarLayout.OnOffsetChangedListener {

   private State mCurrentState = State.IDLE;

   @Override
   public final void onOffsetChanged(AppBarLayout appBarLayout, int i) {
       if (i == 0) {
           if (mCurrentState != State.EXPANDED) {
               onStateChanged(appBarLayout, State.EXPANDED);
           }
           mCurrentState = State.EXPANDED;
       } else if (Math.abs(i) >= appBarLayout.getTotalScrollRange()) {
           if (mCurrentState != State.COLLAPSED) {
               onStateChanged(appBarLayout, State.COLLAPSED);
           }
           mCurrentState = State.COLLAPSED;
       } else {
           if (mCurrentState != State.IDLE) {
               onStateChanged(appBarLayout, State.IDLE);
           }
           mCurrentState = State.IDLE;
       }
       onStateChanged(i);
       Logger.d("滑动的的高度" + i);
   }

   public abstract void onStateChanged(AppBarLayout appBarLayout, State state);

   public void onStateChanged(int i) {
   }

   public enum State {
       EXPANDED,       // 展开状态
       COLLAPSED,      // 折叠状态
       IDLE            // 准备状态
   }
}
activity
   private void initToolbar() {
       mAppBarLayout.addOnOffsetChangedListener(new AppBarStateChangeListener() {
           @Override
           public void onStateChanged(AppBarLayout appBarLayout, State state) {
               if (state == State.EXPANDED) {
                   // 展开状态
                   mTvTitle.setText("");
                   mRlHeader.setVisibility(View.VISIBLE);
               } else if (state == State.COLLAPSED) {
                   // 折叠状态
                   mTvTitle.setText("芭比馒头");
                   mRlHeader.setVisibility(View.GONE);
               } else {
                   mTvTitle.setText("");
                   mRlHeader.setVisibility(View.VISIBLE);
               }
           }

           @Override
           public void onStateChanged(int i) {
               float height = mRlHeader.getHeight();
               float alpha = i / height;
               Logger.d("透明度" + (1 - Math.abs(alpha)));
               mRlHeader.setAlpha(1 - Math.abs(alpha));
           }
       });
   }

上面要注意的是,动态设置 mRlHeader 的显示隐藏,因为透明度有时候不为0的时候,还是会显示出来的


添加减少动画


使用的是属性动画,单这里有一个坑,后面会讲到,尝试过用补间动画,但是由于补间动画的特性,本身的位置不变,达不到预期效果,有兴趣的可以尝试一下

动画的代码

public void animOpen(final ImageView imageView) {
       AnimatorSet animatorSet = new AnimatorSet();
       ObjectAnimator translationAnim = ObjectAnimator.ofFloat(imageView, "translationX", addLeft - reduceLeft, 0);
       ObjectAnimator rotationAnim = ObjectAnimator.ofFloat(imageView, "rotation", 0, 180);
       animatorSet.play(translationAnim).with(rotationAnim);
       animatorSet.setDuration(TIME).start();
   }


public void animClose(final ImageView imageView) {
       AnimatorSet animatorSet = new AnimatorSet();
       ObjectAnimator translationAnim = ObjectAnimator.ofFloat(imageView, "translationX", 0, addLeft - reduceLeft);
       ObjectAnimator rotationAnim = ObjectAnimator.ofFloat(imageView, "rotation", 0, 180);
       animatorSet.play(translationAnim).with(rotationAnim);
       animatorSet.setDuration(TIME).start();
}

动画打开还是关闭

       // 减少
       final ImageView iv_goods_reduce = holder.getView(R.id.iv_goods_reduce);
       iv_goods_reduce.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
           @Override
           public void onGlobalLayout() {
               // 获取减少图标的位置
               reduceLeft = iv_goods_reduce.getLeft();
               iv_goods_reduce.getViewTreeObserver().removeOnGlobalLayoutListener(this);
           }
       });
       iv_goods_reduce.setOnClickListener(new View.OnClickListener() {
           @Override
           public void onClick(View v) {
               int position = holder.getLayoutPosition();
               ShopGoodsBean shopGoodsBean = mGoodsList.get(position);
               int count = shopGoodsBean.getCount();
               count--;
               // 防止过快点击出现多个关闭动画
               if (count == 0) {
                   animClose(iv_goods_reduce);
                   tv_goods_count.setText("");
                   // 考虑到用户点击过快
                   allCount--;
               } else if (count < 0) {
                   // 防止过快点击出现商品数为负数
                   count = 0;
               } else {
                   allCount--;
                   tv_goods_count.setText(String.valueOf(count));
               }
               // 商品的数量是否显示
               if (allCount <= 0) {
                   allCount = 0;
                   mTvShoppingCartCount.setVisibility(View.GONE);
               } else {
                   mTvShoppingCartCount.setText(String.valueOf(allCount));
                   mTvShoppingCartCount.setVisibility(View.VISIBLE);
               }
               shopGoodsBean.setCount(count);
           }
       });
      // 增加
       final ImageView iv_goods_add = holder.getView(R.id.iv_goods_add);
       iv_goods_add.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
           @Override
           public void onGlobalLayout() {
               // 获取增加图标的位置
               addLeft = iv_goods_add.getLeft();
               iv_goods_add.getViewTreeObserver().removeOnGlobalLayoutListener(this);
           }
       });
       iv_goods_add.setOnClickListener(new View.OnClickListener() {
           @Override
           public void onClick(View v) {
               int position = holder.getLayoutPosition();
               ShopGoodsBean shopGoodsBean = mGoodsList.get(position);
               int count = shopGoodsBean.getCount();
               count++;
               allCount++;
               if (allCount > 0) {
                   mTvShoppingCartCount.setVisibility(View.VISIBLE);
               }
               mTvShoppingCartCount.setText(String.valueOf(allCount));![1.gif](https://upload-images.jianshu.io/upload_images/5286943-8616ee25e4dd2edc.gif?imageMogr2/auto-orient/strip)

               if (count == 1) {
                   iv_goods_reduce.setVisibility(View.VISIBLE);
                   animOpen(iv_goods_reduce);
               }
               addGoods2CartAnim(iv_goods_add);
               tv_goods_count.setText(String.valueOf(count));
               shopGoodsBean.setCount(count);
           }
       });

通过 getViewTreeObserver 获取图标的位置,计算距离,做属性动画,同时通过数据层记录,要注意的是,如果手指点击点击过快的时候,会使减少的变为负数,所以我们要做判断,如果为0不减少

640?wx_fmt=gif

你可以看到,减少的图标不见了,而且点击也没效果,很简单,主要是RecycleView的item复用机制,属性动画改变控件位置,所以做完动画位置还原就好了

public void animClose(final ImageView imageView) {
       AnimatorSet animatorSet = new AnimatorSet();
       ObjectAnimator translationAnim = ObjectAnimator.ofFloat(imageView, "translationX", 0, addLeft - reduceLeft);
       ObjectAnimator rotationAnim = ObjectAnimator.ofFloat(imageView, "rotation", 0, 180);
       animatorSet.play(translationAnim).with(rotationAnim);
       animatorSet.setDuration(TIME).start();
       animatorSet.addListener(new AnimatorListenerAdapter() {
           @Override
           public void onAnimationEnd(Animator animation) {
               // TODO: 2018/5/19 因为属性动画会改变位置,所以当结束的时候,要回退的到原来的位置,同时用补间动画的位移不好控制
               ObjectAnimator oa = ObjectAnimator.ofFloat(imageView, "translationX", addLeft - reduceLeft, 0);
               oa.setDuration(0);
               oa.start();
               imageView.setVisibility(View.GONE);
           }
       });
}


贝赛尔曲线动画


一个二阶贝塞尔动画,没有涉及到动态点,比较简单,在你点击的时候,在最外层布局添加一个ImageView,做值动画,动画结束的时候,移除该控件

    /**
    * 贝塞尔曲线动画
    *
    * @param goodsImageView
    */

   public void addGoods2CartAnim(ImageView goodsImageView) {
       final ImageView goods = new ImageView(ShoppingGoodsActivity.this);
       goods.setImageResource(R.mipmap.icon_goods_add);
       int size = Util.dp2px(ShoppingGoodsActivity.this, 24);
       ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(size, size);
       goods.setLayoutParams(lp);
       mCoordinatorLayout.addView(goods);
       // 控制点的位置
       int[] recyclerLocation = new int[2];
       mCoordinatorLayout.getLocationInWindow(recyclerLocation);
       // 加入点的位置起始点
       int[] startLocation = new int[2];
       goodsImageView.getLocationInWindow(startLocation);
       // 购物车的位置终点
       int[] endLocation = new int[2];
       mIvShoppingCart.getLocationInWindow(endLocation);
       // TODO: 2018/5/21 0021 考虑到状态栏的问题,不然会往下偏移状态栏的高度
       int startX = startLocation[0] - recyclerLocation[0];
       int startY = startLocation[1] - recyclerLocation[1];
       // TODO: 2018/5/21 0021 和上面一样
       int endX = endLocation[0] - recyclerLocation[0];
       int endY = endLocation[1] - recyclerLocation[1];
       // 开始绘制贝塞尔曲线
       Path path = new Path();
       // 移动到起始点位置(即贝塞尔曲线的起点)
       path.moveTo(startX, startY);
       // 使用二阶贝塞尔曲线:注意第一个起始坐标越大,贝塞尔曲线的横向距离就会越大,一般按照下面的式子取即可
       path.quadTo((startX + endX) / 2, startY, endX, endY);
       // mPathMeasure用来计算贝塞尔曲线的曲线长度和贝塞尔曲线中间插值的坐标,如果是true,path会形成一个闭环
       final PathMeasure pathMeasure = new PathMeasure(path, false);
       // 属性动画实现(从0到贝塞尔曲线的长度之间进行插值计算,获取中间过程的距离值)
       ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, pathMeasure.getLength());
       // 计算距离
       int tempX = Math.abs(startX - endX);
       int tempY = Math.abs(startY - endY);
       // 根据距离计算时间
       int time = (int) (0.3 * Math.sqrt((tempX * tempX) + tempY * tempY));
       valueAnimator.setDuration(time);
       valueAnimator.start();
       valueAnimator.setInterpolator(new AccelerateInterpolator());
       valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
           @Override
           public void onAnimationUpdate(ValueAnimator animation) {
               // 当插值计算进行时,获取中间的每个值,
               // 这里这个值是中间过程中的曲线长度(下面根据这个值来得出中间点的坐标值)
               float value = (Float) animation.getAnimatedValue();
               // 获取当前点坐标封装到mCurrentPosition
               // boolean getPosTan(float distance, float[] pos, float[] tan) :
               // 传入一个距离distance(0<=distance<=getLength()),然后会计算当前距离的坐标点和切线,pos会自动填充上坐标,这个方法很重要。
               // mCurrentPosition此时就是中间距离点的坐标值
               pathMeasure.getPosTan(value, mCurrentPosition, null);
               // 移动的商品图片(动画图片)的坐标设置为该中间点的坐标
               goods.setTranslationX(mCurrentPosition[0]);
               goods.setTranslationY(mCurrentPosition[1]);
           }
       });
       valueAnimator.addListener(new AnimatorListenerAdapter() {
           @Override
           public void onAnimationEnd(Animator animation) {
               // 移除图片
               mCoordinatorLayout.removeView(goods);
               // 购物车数量增加
               mTvShoppingCartCount.setText(String.valueOf(allCount));
           }
       });
   }


购物车弹窗动画


底部的一个动画效果,大致原理就是,用一个FrameLayout,底部保持不动,上面的ViewGroup做位移动画,同时判断商品个数,动态控制RecycleView的高度
动态设置RecycleView的高度
   private void initAdapter() {
       // 如果商品个数大于指定数时,高度写死,其他wrap_content
       if (list.size() >= 4) {
           ViewGroup.LayoutParams lp = mRvCartGoods.getLayoutParams();
           lp.width = ViewGroup.LayoutParams.MATCH_PARENT;
           lp.height = DensityUtil.dp2px(200);
           mRvCartGoods.setLayoutParams(lp);
       }
       mAdapter = new BaseAdapter(list, R.layout.item_cart_goods, this);
       mRvCartGoods.setLayoutManager(new LinearLayoutManager(mActivity));
       mRvCartGoods.setAdapter(mAdapter);
   }
网上找过很多设置最大值的,都没有效果,后面直接改用代码动态设置
动画效果
private void initScreen() {
       WindowManager wm = (WindowManager) mActivity.getSystemService(Context.WINDOW_SERVICE);
       DisplayMetrics dm = new DisplayMetrics();
       wm.getDefaultDisplay().getMetrics(dm);
       // 获取屏幕的高度
       mHeightPixels = dm.heightPixels;
   }

   public void openAnim() {
       ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(mLlShoppingCart, "translationY", mHeightPixels, 0);
       objectAnimator.setDuration(TIME);
       objectAnimator.start();
   }

   public void closeAnim() {
       ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(mLlShoppingCart, "translationY", 0, mHeightPixels);
       objectAnimator.setDuration(TIME);
       objectAnimator.start();
       objectAnimator.addListener(new AnimatorListenerAdapter() {
           @Override
           public void onAnimationEnd(Animator animation) {
               super.onAnimationEnd(animation);
               dismiss();
           }
       });
}
可以看到,在关闭的时候做了一个动画监听,直接调用dismiss()方法,会直接销毁掉,我们要等到动画执行完毕之后在销毁掉


购物车缓存


storeId为文件名,同时内部用一个map集合储存数据,key为goodsID,value为count,allCount为商铺总数

private void initScreen() {
/**
  * 添加商品缓存
  *
  * @param storeId 商品的id
  */

public ShoppingCartHistoryManager add(String storeId, @NonNull StoreGoodsBean storeGoodsBean) {
   File file = new File(PATH);
   if (!file.exists()) {
     file.mkdirs();
   }
   FileOutputStream fileOutputStream = null;
   ObjectOutputStream objectOutputStream = null;
   try {
     fileOutputStream = new FileOutputStream(file.getAbsolutePath() + File.separator + storeId + FILE_FORMAT);
     objectOutputStream = new ObjectOutputStream(fileOutputStream);
     objectOutputStream.writeObject(storeGoodsBean);
     objectOutputStream.flush();
     objectOutputStream.close();
   } catch (Exception e) {
     e.printStackTrace();
   }
   return this;
 }

 /**
  * 得到商品缓存
  *
  * @param storeId 商铺的id
  */

 public HashMap<String, Integer> get(String storeId) {
   File file = new File(PATH);
   if (!file.exists()) {
     return null;
   }
   FileInputStream FileInputStream = null;
   ObjectInputStream objectInputStream = null;
   StoreGoodsBean storeGoodsBean = null;
   try {
     FileInputStream = new FileInputStream(file.getAbsolutePath() + File.separator + storeId + FILE_FORMAT);
     objectInputStream = new ObjectInputStream(FileInputStream);
     storeGoodsBean = (StoreGoodsBean) objectInputStream.readObject();
     objectInputStream.close();
   } catch (Exception e) {
     e.printStackTrace();
     return null;
   }
   return storeGoodsBean.getHashMap();
 }

 /**
  * 获取商铺选择的总个数
  *
  * @param storeId 商铺id
  * @return
  */

 public int getAllGoodsCount(String storeId) {
   HashMap<String, Integer> hashMap = get(storeId);
   int allCount = 0;
   if (hashMap != null) {
     for (Map.Entry<String, Integer> entry : hashMap.entrySet()) {
       Integer value = entry.getValue();
       if (value != 0) {
         allCount += value;
       }
     }
   }
   return allCount;
 }

 /**
  * 删除商铺缓存,如果数量为0
  *
  * @param storeId 商铺的id
  */

 public ShoppingCartHistoryManager delete(@NonNull String storeId) {
   File file = new File(PATH, storeId + FILE_FORMAT);
   if (file.exists()) {
     file.delete();
   }
   return this;
 }

   /**
    * 删除商铺缓存,如果数量为0
    *
    * @param ShopId 商铺的id
    */

   public ShoppingCartHistoryManager delete(@NonNull int ShopId) {
       File file = new File(PATH, +ShopId + FILE_FORMAT);
       if (file.exists()) {
           file.delete();
       }
       return this;
   }
退出页面时,根据商铺的总数是否为0,选择删除数据(如果文件之前存在)还是保存数据
    @Override
   protected void onDestroy() {
       super.onDestroy();
       if (allCount != 0) {
           HashMap<String, Integer> hashMap = new HashMap<>();
           StoreGoodsBean storeGoodsBean = new StoreGoodsBean(hashMap);
           for (ShopGoodsBean bean : mGoodsList) {
               int count = bean.getCount();
               String goodsId = bean.getGoodsId();
               if (count != 0) {
                   hashMap.put(goodsId, count);
               }
           }
           ShoppingCartHistoryManager.getInstance().add(SHOP_ID, storeGoodsBean);
       } else {
           ShoppingCartHistoryManager.getInstance().delete(SHOP_ID);
       }
   }
进入页面的时候,获取缓存数据(如果存在)
private void initData() {
       int id = 0x100;
       HashMap<String, Integer> hashMap = ShoppingCartHistoryManager.getInstance().get(SHOP_ID);
       this.allCount = ShoppingCartHistoryManager.getInstance().getAllGoodsCount(SHOP_ID);
       showToast("商品总数" + allCount);
       // 根据缓存是否显示
       mTvShoppingCartCount.setVisibility(allCount == 0 ? View.GONE : View.VISIBLE);
       mTvShoppingCartCount.setText(String.valueOf(allCount));
       // TODO: 2018/6/5 0005 模拟请求到的数据
       for (int i = 0; i < 10; i++) {
           mGoodsList.add(new ShopGoodsBean(0, "小猪包套餐" + i, id++ + ""));
       }
       if (hashMap != null) {
           for (ShopGoodsBean bean : mGoodsList) {
               String goodsId = bean.getGoodsId();
               if (hashMap.containsKey(goodsId)) {
                   Integer count = hashMap.get(goodsId);
                   bean.setCount(count);
               }
           }
       }
}
在最外面的商铺列表通过storeId获取商铺总数
this.allCount =ShoppingCartHistoryManager.getInstance().getAllGoodsCount(SHOP_ID);
github:
https://github.com/GongWnbo/SuperRecycleView


欢迎长按下图 -> 识别图中二维码

或者 扫一扫 关注我的公众号

640.png?

640?wx_fmt=jpeg

猜你喜欢

转载自blog.csdn.net/c10wtiybq1ye3/article/details/80729972