简单购物车案例

购物车功能描述

第一次进入购物车页面,购物车里面是空的,同时提示去逛手机商场, 如 首次进入的页面 图所示。接着去商场页面选购手机,随便挑了几部手机加入购物车,再返回购物车页面,即可看 到购物车的商品列表,如 购物车已选列表图 所示,有商品图片、名称、数量、单价、总价等等信息。当然购物车并 不仅仅只是展示待购买的商品,还要支持最终购买的结算操作、支持清空购物车,长按删除单项订单等功能。

购物车的存在感很强,不仅仅在购物车页面才能看到购物车。往往在商场页面,甚至商品详情页面,都 会看到某个角落冒出购物车图标。一旦有新商品加入购物车,购物车图标上的商品数量立马加一。当然,用户也能点击购物车图标直接跳到购物车页面。商场页面除了商品列表之外,页面右上角还有一个购物车图标,用户把商品加购物车,那么图标上的数字也会加一。

功能需求

  • 购物车存放着用户准备购买的商品,一开始是空的,随着商品被加入购物车,购物车中就会显示已添加的商品列表。

  • 除了购物车页面,其它页面(如商场频道页面、商品详情页面),都可能在右上角或者右 下角找到购物车图标。购物车图标上会显示已添加的商品数量,且商品数量是实时更新的。

  • 购物车页面、商场频道页面、商品详情页面多处都会显示商品的小图或者大图

界面设计

  • 线性布局LinearLayout:购物车界面从上往下排列,垂直方向的线性布局

  • 网格布局GridLayout:商场页面的陈列橱柜,允许分行分列展示商品

  • 相对布局RelativeLayout:页面右上角的购物车图标,图标右上角又有数字标记,按照指定方位排列控件

  • 其他常见控件尚有文本视图TextView、图像视图ImageView,按钮控件Button等

存储技术

  • 数据库SQLite:最直观的是数据库,购物车里的商品列表一定放在SQLite中,增删改查

  • 全局内存:购物车图标右上角的数字表示购物车中的商品数量,该数值建议保存在全局内存中,这样不必每次都到数据库中执行count操作。

  • 存储卡文件:App把下载的商品图片保存在存储卡中,这样下次就能直接从存储卡获取商品图片,加快浏览速度。

  • 共享参数SharedPreferences:是否首次访问网络图片,这个标志位推荐放在共享参数中, 需要持久化存储,并且只有一个参数信息

效果图

首次进入的页面图

商品展示列表图

购物车已选列表图

手机详情页面图

长按删除订单图

图片

主程序

ShoppingChannelActivity.java
package com.kcs.shoppingcart;import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.GridView;
import android.widget.TextView;import androidx.appcompat.app.AppCompatActivity;import com.kcs.shoppingcart.adapter.GoodsAdapter;
import com.kcs.shoppingcart.datebase.ShoppingDBHelper;
import com.kcs.shoppingcart.entity.GoodsInfo;
import com.kcs.shoppingcart.utils.ToastUtil;import java.util.List;public class ShoppingChannelActivity extends AppCompatActivity implements View.OnClickListener, GoodsAdapter.AddCartListener {/*** 声明一个商品数据库的帮助器对象*/private ShoppingDBHelper mDBHelper;private TextView tv_count;private GridView gv_channel;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_shopping_channel);TextView tv_title = findViewById(R.id.tv_title);tv_title.setText("手机商场");tv_count = findViewById(R.id.tv_count);gv_channel = findViewById(R.id.gv_channel);findViewById(R.id.iv_back).setOnClickListener(this);findViewById(R.id.iv_cart).setOnClickListener(this);mDBHelper = ShoppingDBHelper.getInstance(this);mDBHelper.openReadLink();mDBHelper.openWriteLink();// 从数据库查询出商品信息,并展示showGoods();}@Overrideprotected void onResume() {super.onResume();// 查询购物车商品总数,并展示showCartInfoTotal();}/*** 查询购物车商品总数,并展示*/private void showCartInfoTotal() {int count = mDBHelper.countCartInfo();MyApplication.getInstance().goodsCount = count;tv_count.setText(String.valueOf(count));}private void showGoods() {// 查询商品数据库中的所有商品记录List<GoodsInfo> list = mDBHelper.queryAllGoodsInfo();GoodsAdapter adapter = new GoodsAdapter(this, list,this);gv_channel.setAdapter(adapter);}/***  把指定编号的商品添加到购物车* @param goodsId* @param goodsName*/@Overridepublic void addToCart(int goodsId, String goodsName) {// 购物车商品数量+1int count = ++MyApplication.getInstance().goodsCount;tv_count.setText(String.valueOf(count));mDBHelper.insertCartInfo(goodsId);ToastUtil.show(this, "已添加一部" + goodsName + "到购物车");}@Overrideprotected void onDestroy() {super.onDestroy();mDBHelper.closeLink();}@Overridepublic void onClick(View v) {switch (v.getId()) {case R.id.iv_back:// 点击了返回图标,关闭当前页面finish();break;case R.id.iv_cart:// 点击了购物车图标// 从商场页面跳到购物车页面Intent intent = new Intent(this, ShoppingCartActivity.class);// 设置启动标志,避免多次返回同一页面的intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);startActivity(intent);break;default:break;}}
}
ShoppingDetailActivity.java
import androidx.appcompat.app.AppCompatActivity;import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;import com.dongnaoedu.chapter06.database.ShoppingDBHelper;
import com.dongnaoedu.chapter06.enity.GoodsInfo;
import com.dongnaoedu.chapter06.util.ToastUtil;public class ShoppingDetailActivity extends AppCompatActivity implements View.OnClickListener {private TextView tv_title;private TextView tv_count;private TextView tv_goods_price;private TextView tv_goods_desc;private ImageView iv_goods_pic;private ShoppingDBHelper mDBHelper;private int mGoodsId;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_shopping_detail);tv_title = findViewById(R.id.tv_title);tv_count = findViewById(R.id.tv_count);tv_goods_price = findViewById(R.id.tv_goods_price);tv_goods_desc = findViewById(R.id.tv_goods_desc);iv_goods_pic = findViewById(R.id.iv_goods_pic);findViewById(R.id.iv_back).setOnClickListener(this);findViewById(R.id.iv_cart).setOnClickListener(this);findViewById(R.id.btn_add_cart).setOnClickListener(this);tv_count.setText(String.valueOf(MyApplication.getInstance().goodsCount));mDBHelper = ShoppingDBHelper.getInstance(this);}@Overrideprotected void onResume() {super.onResume();showDetail();}private void showDetail() {// 获取上一个页面传来的商品编号mGoodsId = getIntent().getIntExtra("goods_id", 0);if (mGoodsId > 0) {// 根据商品编号查询商品数据库中的商品记录GoodsInfo info = mDBHelper.queryGoodsInfoById(mGoodsId);tv_title.setText(info.name);tv_goods_desc.setText(info.description);tv_goods_price.setText(String.valueOf((int) info.price));iv_goods_pic.setImageURI(Uri.parse(info.picPath));}}@Overridepublic void onClick(View v) {switch (v.getId()) {case R.id.iv_back:finish();break;case R.id.iv_cart:Intent intent = new Intent(this, ShoppingCartActivity.class);startActivity(intent);break;case R.id.btn_add_cart:addToCart(mGoodsId);break;}}private void addToCart(int goodsId) {// 购物车商品数量+1int count = ++MyApplication.getInstance().goodsCount;tv_count.setText(String.valueOf(count));mDBHelper.insertCartInfo(goodsId);ToastUtil.show(this, "成功添加至购物车");}
}
ShoppingCartActivity.java
package com.kcs.shoppingcart;import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;import com.kcs.shoppingcart.adapter.CartAdapter;
import com.kcs.shoppingcart.datebase.ShoppingDBHelper;
import com.kcs.shoppingcart.entity.CartInfo;
import com.kcs.shoppingcart.entity.GoodsInfo;
import com.kcs.shoppingcart.utils.ToastUtil;import java.util.HashMap;
import java.util.List;
import java.util.Map;public class ShoppingCartActivity extends AppCompatActivity implements View.OnClickListener, AdapterView.OnItemClickListener, AdapterView.OnItemLongClickListener {private TextView tv_count;private ListView lv_cart;private ShoppingDBHelper mDBHelper;/*** 声明一个购物车中的商品信息列表*/private List<CartInfo> mCartList;/*** 声明一个根据商品编号查找商品信息的映射,把商品信息缓存起来,这样不用每一次都去查询数据库*/private Map<Integer, GoodsInfo> mGoodsMap = new HashMap<>();private TextView tv_total_price;private LinearLayout ll_empty;private LinearLayout ll_content;private CartAdapter mCartAdapter;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_shopping_cart);TextView tv_title = findViewById(R.id.tv_title);tv_title.setText("购物车");lv_cart = findViewById(R.id.lv_cart);tv_total_price = findViewById(R.id.tv_total_price);tv_count = findViewById(R.id.tv_count);tv_count.setText(String.valueOf(MyApplication.getInstance().goodsCount));mDBHelper = ShoppingDBHelper.getInstance(this);findViewById(R.id.iv_back).setOnClickListener(this);findViewById(R.id.btn_shopping_channel).setOnClickListener(this);findViewById(R.id.btn_clear).setOnClickListener(this);findViewById(R.id.btn_settle).setOnClickListener(this);ll_empty = findViewById(R.id.ll_empty);ll_content = findViewById(R.id.ll_content);}@Overrideprotected void onResume() {super.onResume();showCart();}/*** 展示购物车中的商品列表*/private void showCart() {// 查询购物车数据库中所有的商品记录mCartList = mDBHelper.queryAllCartInfo();if (mCartList.size() == 0) {return;}for (CartInfo info : mCartList) {// 根据商品编号查询商品数据库中的商品记录GoodsInfo goods = mDBHelper.queryGoodsInfoById(info.goodsId);mGoodsMap.put(info.goodsId, goods);info.goods = goods;}mCartAdapter = new CartAdapter(this, mCartList);lv_cart.setAdapter(mCartAdapter);// 给商品行添加点击事件。点击商品行跳到商品的详情页lv_cart.setOnItemClickListener(this);// 给商品行添加长按事件。长按商品行就删除该商品lv_cart.setOnItemLongClickListener(this);// 重新计算购物车中的商品总金额refreshTotalPrice();}private void deleteGoods(CartInfo info) {MyApplication.getInstance().goodsCount -= info.count;// 从购物车的数据库中删除商品mDBHelper.deleteCartInfoByGoodsId(info.goodsId);// 从购物车的列表中删除商品CartInfo removed = null;for (CartInfo cartInfo : mCartList) {if (cartInfo.goodsId == info.goodsId) {removed = cartInfo;break;}}mCartList.remove(removed);// 显示最新的商品数量showCount();ToastUtil.show(this, "已从购物车删除" + mGoodsMap.get(info.goodsId).name);mGoodsMap.remove(info.goodsId);// 刷新购物车中所有商品的总金额refreshTotalPrice();}/*** 显示购物车图标中的商品数量*/private void showCount() {tv_count.setText(String.valueOf(MyApplication.getInstance().goodsCount));// 购物车中没有商品,显示“空空如也”if (MyApplication.getInstance().goodsCount == 0) {ll_empty.setVisibility(View.VISIBLE);ll_content.setVisibility(View.GONE);// 通知适配器发生了数据变化mCartAdapter.notifyDataSetChanged();} else {ll_content.setVisibility(View.VISIBLE);ll_empty.setVisibility(View.GONE);}}/*** 重新计算购物车中的商品总金额*/private void refreshTotalPrice() {int totalPrice = 0;for (CartInfo info : mCartList) {GoodsInfo goods = mGoodsMap.get(info.goodsId);totalPrice += goods.price * info.count;}tv_total_price.setText(String.valueOf(totalPrice));}@Overridepublic void onClick(View v) {switch (v.getId()) {case R.id.iv_back:// 点击了返回图标// 关闭当前页面finish();break;case R.id.btn_shopping_channel:// 从购物车页面跳到商场页面Intent intent = new Intent(this, com.kcs.shoppingcart.ShoppingChannelActivity.class);intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);startActivity(intent);break;case R.id.btn_clear:// 清空购物车数据库mDBHelper.deleteAllCartInfo();MyApplication.getInstance().goodsCount = 0;// 显示最新的商品数量showCount();ToastUtil.show(this, "购物车已清空");break;case R.id.btn_settle:// 点击了“结算”按钮AlertDialog.Builder builder = new AlertDialog.Builder(this);builder.setTitle("结算商品");builder.setMessage("客官抱歉,支付功能尚未开通");builder.setPositiveButton("我知道了", null);builder.create().show();break;default:break;}}/*** 给商品行添加点击事件。点击商品行跳到商品的详情页*/@Overridepublic void onItemClick(AdapterView<?> parent, View view, int position, long id) {Intent intent = new Intent(ShoppingCartActivity.this, com.kcs.shoppingcart.ShoppingDetailActivity.class);intent.putExtra("goods_id", mCartList.get(position).goodsId);startActivity(intent);}/***给商品行添加长按事件。长按商品行就删除该商品*/@Overridepublic boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {CartInfo info = mCartList.get(position);AlertDialog.Builder builder = new AlertDialog.Builder(ShoppingCartActivity.this);builder.setMessage("是否从购物车删除" + info.goods.name + "?");builder.setPositiveButton("是", (dialog, which) -> {// 从集合中移除数据mCartList.remove(position);// 通知适配器发生了数据变化mCartAdapter.notifyDataSetChanged();// 删除该商品deleteGoods(info);});builder.setNegativeButton("否", null);builder.create().show();return true;}
}

MyApplication.java

package com.dongnaoedu.chapter06;import android.app.Application;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Environment;
import android.util.Log;import androidx.annotation.NonNull;
import androidx.room.Room;import com.dongnaoedu.chapter06.database.ShoppingDBHelper;
import com.dongnaoedu.chapter06.enity.GoodsInfo;
import com.dongnaoedu.chapter06.util.FileUtil;
import com.dongnaoedu.chapter06.util.SharedUtil;import java.io.File;
import java.util.HashMap;
import java.util.List;public class MyApplication extends Application {// 购物车中的商品总数量public int goodsCount;public static MyApplication getInstance() {return mApp;}//在App启动时调用@Overridepublic void onCreate() {super.onCreate();mApp = this;Log.d("ning", "MyApplication onCreate");// 初始化商品信息initGoodsInfo();}private void initGoodsInfo() {// 获取共享参数保存的是否首次打开参数boolean isFirst = SharedUtil.getInstance(this).readBoolean("first", true);// 获取当前App的私有下载路径String directory = getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS).toString() + File.separatorChar;if (isFirst) {// 模拟网络图片下载List<GoodsInfo> list = GoodsInfo.getDefaultList();for (GoodsInfo info : list) {Bitmap bitmap = BitmapFactory.decodeResource(getResources(), info.pic);String path = directory + info.id + ".jpg";// 往存储卡保存商品图片FileUtil.saveImage(path, bitmap);// 回收位图对象bitmap.recycle();info.picPath = path;}// 打开数据库,把商品信息插入到表中ShoppingDBHelper dbHelper = ShoppingDBHelper.getInstance(this);dbHelper.openWriteLink();dbHelper.insertGoodsInfos(list);dbHelper.closeLink();// 把是否首次打开写入共享参数SharedUtil.getInstance(this).writeBoolean("first", false);}}}

适配器

package:adapter

CartAdapter.java
package com.kcs.shoppingcart.adapter;import android.content.Context;
import android.net.Uri;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;import com.kcs.shoppingcart.R;
import com.kcs.shoppingcart.entity.CartInfo;import java.util.List;public class CartAdapter extends BaseAdapter {private Context mContext;private List<CartInfo> mCartList;public CartAdapter(Context mContext, List<CartInfo> mCartList) {this.mContext = mContext;this.mCartList = mCartList;}@Overridepublic int getCount() {return mCartList.size();}@Overridepublic Object getItem(int position) {return mCartList.get(position);}@Overridepublic long getItemId(int position) {return position;}@Overridepublic View getView(int position, View convertView, ViewGroup parent) {ViewHolder holder;if (convertView == null) {holder = new ViewHolder();// 获取布局文件item_cart.xml的根视图convertView = LayoutInflater.from(mContext).inflate(R.layout.item_cart, null);holder.iv_thumb = convertView.findViewById(R.id.iv_thumb);holder.tv_name = convertView.findViewById(R.id.tv_name);holder.tv_desc = convertView.findViewById(R.id.tv_desc);holder.tv_count = convertView.findViewById(R.id.tv_count);holder.tv_price = convertView.findViewById(R.id.tv_price);holder.tv_sum = convertView.findViewById(R.id.tv_sum);convertView.setTag(holder);} else {holder = (ViewHolder) convertView.getTag();}CartInfo info = mCartList.get(position);holder.iv_thumb.setImageURI(Uri.parse(info.goods.picPath));holder.tv_name.setText(info.goods.name);holder.tv_desc.setText(info.goods.description);holder.tv_count.setText(String.valueOf(info.count));holder.tv_price.setText(String.valueOf((int) info.goods.price));// 设置商品总价holder.tv_sum.setText(String.valueOf((int) (info.count * info.goods.price)));return convertView;}public final class ViewHolder {public ImageView iv_thumb;public TextView tv_name;public TextView tv_desc;public TextView tv_count;public TextView tv_price;public TextView tv_sum;}
}

GoodsAdapter.java

package com.kcs.shoppingcart.adapter;import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;import com.kcs.shoppingcart.R;
import com.kcs.shoppingcart.ShoppingDetailActivity;
import com.kcs.shoppingcart.entity.GoodsInfo;import java.util.List;public class GoodsAdapter extends BaseAdapter {private Context mContext;private List<GoodsInfo> mGoodsInfo;public GoodsAdapter(Context mContext, List<GoodsInfo> mGoodsInfo, AddCartListener mAddCartListener) {this.mContext = mContext;this.mGoodsInfo = mGoodsInfo;this.mAddCartListener = mAddCartListener;}@Overridepublic int getCount() {return mGoodsInfo.size();}@Overridepublic Object getItem(int position) {return position;}@Overridepublic long getItemId(int position) {return position;}@Overridepublic View getView(int position, View convertView, ViewGroup parent) {GoodsInfo info = mGoodsInfo.get(position);ViewHolder holder;if (convertView == null) {convertView = LayoutInflater.from(mContext).inflate(R.layout.item_goods, null);holder = new ViewHolder();holder.iv_thumb = convertView.findViewById(R.id.iv_thumb);holder.tv_name = convertView.findViewById(R.id.tv_name);holder.tv_price = convertView.findViewById(R.id.tv_price);holder.btn_add = convertView.findViewById(R.id.btn_add);convertView.setTag(holder);} else {holder = (ViewHolder) convertView.getTag();}// 给控件设置值holder.iv_thumb.setImageURI(Uri.parse(info.picPath));holder.tv_name.setText(info.name);holder.tv_price.setText(String.valueOf((int) info.price));// 添加到购物车holder.btn_add.setOnClickListener(v -> {mAddCartListener.addToCart(info.id, info.name);});//点击商品图片,跳转到商品详情页面holder.iv_thumb.setOnClickListener(v -> {Intent intent = new Intent(mContext, ShoppingDetailActivity.class);intent.putExtra("goods_id", info.id);mContext.startActivity(intent);});return convertView;}public final class ViewHolder {public ImageView iv_thumb;public TextView tv_name;public TextView tv_price;public Button btn_add;}/*** 声明一个加入购物车的监听器对象*/private AddCartListener mAddCartListener;/*** 定义一个加入购物车的监听器接口*/public interface AddCartListener {void addToCart(int goodsId, String goodsName);}
}

工具类

package util:

ToastUitl.java

package com.dongnaoedu.chapter06.util;import android.content.Context;
import android.widget.Toast;public class ToastUtil {public static void show(Context ctx, String desc) {Toast.makeText(ctx, desc, Toast.LENGTH_SHORT).show();}}

SharedUtil.java

import android.content.Context;
import android.content.SharedPreferences;public class SharedUtil {private static SharedUtil mUtil;private SharedPreferences preferences;public static SharedUtil getInstance(Context ctx) {if (mUtil == null) {mUtil = new SharedUtil();mUtil.preferences = ctx.getSharedPreferences("shopping", Context.MODE_PRIVATE);}return mUtil;}public void writeBoolean(String key, boolean value) {SharedPreferences.Editor editor = preferences.edit();editor.putBoolean(key, value);editor.commit();}public boolean readBoolean(String key, boolean defaultValue) {return preferences.getBoolean(key, defaultValue);}}

FileUtil.java

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;public class FileUtil {// 把位图数据保存到指定路径的图片文件public static void saveImage(String path, Bitmap bitmap) {FileOutputStream fos = null;try {fos = new FileOutputStream(path);// 把位图数据压缩到文件输出流中bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);} catch (Exception e) {e.printStackTrace();} finally {if (fos != null) {try {fos.close();} catch (IOException e) {e.printStackTrace();}}}}// 从指定路径的图片文件中读取位图数据public static Bitmap openImage(String path) {Bitmap bitmap = null;FileInputStream fis = null;try {fis = new FileInputStream(path);bitmap = BitmapFactory.decodeStream(fis);} catch (Exception e) {e.printStackTrace();} finally {if (fis != null) {try {fis.close();} catch (IOException e) {e.printStackTrace();}}}return bitmap;}
}

实体类

package pojo:

CarInfo.java

package com.kcs.shoppingcart.entity;//购物车信息
public class CartInfo {public int id;/*** 商品编号*/public int goodsId;/*** 商品数量*/public int count;/*** 商品信息*/public GoodsInfo goods;public CartInfo() {}public CartInfo(int id, int goodsId, int count) {this.id = id;this.goodsId = goodsId;this.count = count;this.goods = new GoodsInfo();}
}
GoodsInfo.java
import com.dongnaoedu.chapter06.R;import java.util.ArrayList;public class GoodsInfo {public int id;// 名称public String name;// 描述public String description;// 价格public float price;// 大图的保存路径public String picPath;// 大图的资源编号public int pic;// 声明一个手机商品的名称数组private static String[] mNameArray = {"iPhone11", "Mate30", "小米10", "OPPO Reno3", "vivo X30", "荣耀30S"};// 声明一个手机商品的描述数组private static String[] mDescArray = {"Apple iPhone11 256GB 绿色 4G全网通手机","华为 HUAWEI Mate30 8GB+256GB 丹霞橙 5G全网通 全面屏手机","小米 MI10 8GB+128GB 钛银黑 5G手机 游戏拍照手机","OPPO Reno3 8GB+128GB 蓝色星夜 双模5G 拍照游戏智能手机","vivo X30 8GB+128GB 绯云 5G全网通 美颜拍照手机","荣耀30S 8GB+128GB 蝶羽红 5G芯片 自拍全面屏手机"};// 声明一个手机商品的价格数组private static float[] mPriceArray = {6299, 4999, 3999, 2999, 2998, 2399};// 声明一个手机商品的大图数组private static int[] mPicArray = {R.drawable.iphone, R.drawable.huawei, R.drawable.xiaomi,R.drawable.oppo, R.drawable.vivo, R.drawable.rongyao};// 获取默认的手机信息列表public static ArrayList<GoodsInfo> getDefaultList() {ArrayList<GoodsInfo> goodsList = new ArrayList<GoodsInfo>();for (int i = 0; i < mNameArray.length; i++) {GoodsInfo info = new GoodsInfo();info.id = i;info.name = mNameArray[i];info.description = mDescArray[i];info.price = mPriceArray[i];info.pic = mPicArray[i];goodsList.add(info);}return goodsList;}
}

购物车数据库类

package database:

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;import com.dongnaoedu.chapter06.enity.CartInfo;
import com.dongnaoedu.chapter06.enity.GoodsInfo;import java.util.ArrayList;
import java.util.List;public class ShoppingDBHelper extends SQLiteOpenHelper {private static final String DB_NAME = "shopping.db";// 商品信息表private static final String TABLE_GOODS_INFO = "goods_info";// 购物车信息表private static final String TABLE_CART_INFO = "cart_info";private static final int DB_VERSION = 1;private static ShoppingDBHelper mHelper = null;private SQLiteDatabase mRDB = null;private SQLiteDatabase mWDB = null;private ShoppingDBHelper(Context context) {super(context, DB_NAME, null, DB_VERSION);}// 利用单例模式获取数据库帮助器的唯一实例public static ShoppingDBHelper getInstance(Context context) {if (mHelper == null) {mHelper = new ShoppingDBHelper(context);}return mHelper;}// 打开数据库的读连接public SQLiteDatabase openReadLink() {if (mRDB == null || !mRDB.isOpen()) {mRDB = mHelper.getReadableDatabase();}return mRDB;}// 打开数据库的写连接public SQLiteDatabase openWriteLink() {if (mWDB == null || !mWDB.isOpen()) {mWDB = mHelper.getWritableDatabase();}return mWDB;}// 关闭数据库连接public void closeLink() {if (mRDB != null && mRDB.isOpen()) {mRDB.close();mRDB = null;}if (mWDB != null && mWDB.isOpen()) {mWDB.close();mWDB = null;}}// 创建数据库,执行建表语句@Overridepublic void onCreate(SQLiteDatabase db) {// 创建商品信息表String sql = "CREATE TABLE IF NOT EXISTS " + TABLE_GOODS_INFO +"(_id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL," +" name VARCHAR NOT NULL," +" description VARCHAR NOT NULL," +" price FLOAT NOT NULL," +" pic_path VARCHAR NOT NULL);";db.execSQL(sql);// 创建购物车信息表sql = "CREATE TABLE IF NOT EXISTS " + TABLE_CART_INFO +"(_id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL," +" goods_id INTEGER NOT NULL," +" count INTEGER NOT NULL);";db.execSQL(sql);}@Overridepublic void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {}// 添加多条商品信息public void insertGoodsInfos(List<GoodsInfo> list) {// 插入多条记录,要么全部成功,要么全部失败try {mWDB.beginTransaction();for (GoodsInfo info : list) {ContentValues values = new ContentValues();values.put("name", info.name);values.put("description", info.description);values.put("price", info.price);values.put("pic_path", info.picPath);mWDB.insert(TABLE_GOODS_INFO, null, values);}mWDB.setTransactionSuccessful();} catch (Exception e) {e.printStackTrace();} finally {mWDB.endTransaction();}}// 查询所有的商品信息public List<GoodsInfo> queryAllGoodsInfo() {String sql = "select * from " + TABLE_GOODS_INFO;List<GoodsInfo> list = new ArrayList<>();Cursor cursor = mRDB.rawQuery(sql, null);while (cursor.moveToNext()) {GoodsInfo info = new GoodsInfo();info.id = cursor.getInt(0);info.name = cursor.getString(1);info.description = cursor.getString(2);info.price = cursor.getFloat(3);info.picPath = cursor.getString(4);list.add(info);}cursor.close();return list;}// 添加商品到购物车public void insertCartInfo(int goodsId) {// 如果购物车中不存在该商品,添加一条信息CartInfo cartInfo = queryCartInfoByGoodsId(goodsId);ContentValues values = new ContentValues();values.put("goods_id", goodsId);if (cartInfo == null) {values.put("count", 1);mWDB.insert(TABLE_CART_INFO, null, values);} else {// 如果购物车中已经存在该商品,更新商品数量values.put("_id", cartInfo.id);values.put("count", ++cartInfo.count);mWDB.update(TABLE_CART_INFO, values, "_id=?", new String[]{String.valueOf(cartInfo.id)});}}// 根据商品信息ID查询购物车信息private CartInfo queryCartInfoByGoodsId(int goodsId) {Cursor cursor = mRDB.query(TABLE_CART_INFO, null, "goods_id=?", new String[]{String.valueOf(goodsId)}, null, null, null);CartInfo info = null;if (cursor.moveToNext()) {info = new CartInfo();info.id = cursor.getInt(0);info.goodsId = cursor.getInt(1);info.count = cursor.getInt(2);}return info;}// 统计购物车中商品的总数量public int countCartInfo() {int count = 0;String sql = "select sum(count) from " + TABLE_CART_INFO;Cursor cursor = mRDB.rawQuery(sql, null);if (cursor.moveToNext()) {count = cursor.getInt(0);}return count;}// 查询购物车中所有的信息列表public List<CartInfo> queryAllCartInfo() {List<CartInfo> list = new ArrayList<>();Cursor cursor = mRDB.query(TABLE_CART_INFO, null, null, null, null, null, null);while (cursor.moveToNext()) {CartInfo info = new CartInfo();info.id = cursor.getInt(0);info.goodsId = cursor.getInt(1);info.count = cursor.getInt(2);list.add(info);}return list;}// 根据商品ID查询商品信息public GoodsInfo queryGoodsInfoById(int goodsId) {GoodsInfo info = null;Cursor cursor = mRDB.query(TABLE_GOODS_INFO, null, "_id=?", new String[]{String.valueOf(goodsId)}, null, null, null);if (cursor.moveToNext()) {info = new GoodsInfo();info.id = cursor.getInt(0);info.name = cursor.getString(1);info.description = cursor.getString(2);info.price = cursor.getFloat(3);info.picPath = cursor.getString(4);}return info;}// 根据商品ID删除购物车信息public void deleteCartInfoByGoodsId(int goodsId) {mWDB.delete(TABLE_CART_INFO, "goods_id=?", new String[]{String.valueOf(goodsId)});}// 删除所有购物车信息public void deleteAllCartInfo() {mWDB.delete(TABLE_CART_INFO, "1=1", null);}
}

布局文件

activity_shopping_channel.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:background="@color/orange"android:orientation="vertical" ><include layout="@layout/title_shopping" /><GridViewandroid:id="@+id/gv_channel"android:layout_width="match_parent"android:layout_height="wrap_content"android:numColumns="2" /></LinearLayout>

activity_shopping_detail.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:background="@color/orange"android:orientation="vertical"><include layout="@layout/title_shopping" /><ScrollViewandroid:layout_width="match_parent"android:layout_height="wrap_content"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="vertical"><ImageViewandroid:id="@+id/iv_goods_pic"android:layout_width="match_parent"android:layout_height="350dp"android:scaleType="fitCenter"tools:src="@drawable/xiaomi" /><TextViewandroid:id="@+id/tv_goods_price"android:layout_width="match_parent"android:layout_height="wrap_content"android:paddingLeft="5dp"android:textColor="@color/red"android:textSize="22sp"tools:text="1990" /><TextViewandroid:id="@+id/tv_goods_desc"android:layout_width="match_parent"android:layout_height="wrap_content"android:paddingLeft="5dp"android:textColor="@color/black"android:textSize="15sp"tools:text="小米 MI10 8GB+128GB 钛银黑 5G手机 游戏拍照手机" /><Buttonandroid:id="@+id/btn_add_cart"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="加入购物车"android:textColor="@color/black"android:textSize="17sp" /></LinearLayout></ScrollView></LinearLayout>

activity_shopping_car.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:background="@color/orange"android:orientation="vertical"><include layout="@layout/title_shopping" /><ScrollViewandroid:layout_width="match_parent"android:layout_height="wrap_content"><RelativeLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"><LinearLayoutandroid:id="@+id/ll_content"android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="vertical"android:visibility="visible"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal"><TextViewandroid:layout_width="85dp"android:layout_height="wrap_content"android:gravity="center"android:text="图片"android:textColor="@color/black"android:textSize="15sp" /><TextViewandroid:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="3"android:gravity="center"android:text="名称"android:textColor="@color/black"android:textSize="15sp" /><TextViewandroid:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:gravity="center"android:text="数量"android:textColor="@color/black"android:textSize="15sp" /><TextViewandroid:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:gravity="center"android:text="单价"android:textColor="@color/black"android:textSize="15sp" /><TextViewandroid:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:gravity="center"android:text="总价"android:textColor="@color/black"android:textSize="15sp" /></LinearLayout><LinearLayoutandroid:id="@+id/ll_cart"android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="vertical" /><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal"android:padding="0dp"><Buttonandroid:id="@+id/btn_clear"android:layout_width="wrap_content"android:layout_height="wrap_content"android:gravity="center"android:text="清空"android:textColor="@color/black"android:textSize="17sp" /><TextViewandroid:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:gravity="center|right"android:text="总金额:"android:textColor="@color/black"android:textSize="17sp" /><TextViewandroid:id="@+id/tv_total_price"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginRight="10dp"android:gravity="center|left"android:textColor="@color/red"android:textSize="25sp" /><Buttonandroid:id="@+id/btn_settle"android:layout_width="wrap_content"android:layout_height="wrap_content"android:gravity="center"android:text="结算"android:textColor="@color/black"android:textSize="17sp" /></LinearLayout></LinearLayout><LinearLayoutandroid:id="@+id/ll_empty"android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="vertical"android:visibility="gone"tools:visibility="visible"><TextViewandroid:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginTop="100dp"android:layout_marginBottom="100dp"android:gravity="center"android:text="哎呀,购物车空空如也,快去选购商品吧"android:textColor="@color/black"android:textSize="17sp" /><Buttonandroid:id="@+id/btn_shopping_channel"android:layout_width="match_parent"android:layout_height="wrap_content"android:gravity="center"android:text="逛逛手机商场"android:textColor="@color/black"android:textSize="17sp" /></LinearLayout></RelativeLayout></ScrollView></LinearLayout>

购物车列表清单

item_cart.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="wrap_content"android:background="@color/white"android:orientation="horizontal"><ImageViewandroid:id="@+id/iv_thumb"android:layout_width="85dp"android:layout_height="85dp"android:scaleType="fitCenter"tools:src="@drawable/xiaomi"/><LinearLayoutandroid:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="3"android:orientation="vertical"><TextViewandroid:id="@+id/tv_name"android:layout_width="match_parent"android:layout_height="0dp"android:layout_weight="2"android:gravity="left|center"android:textColor="@color/black"android:textSize="17sp"tools:text="小米手机"/><TextViewandroid:id="@+id/tv_desc"android:layout_width="match_parent"android:layout_height="0dp"android:layout_weight="3"android:gravity="left|center"android:textColor="@color/black"android:textSize="12sp"tools:text="小米 MI10 8GB+128GB 钛银黑 5G手机 游戏拍照手机"/></LinearLayout><TextViewandroid:id="@+id/tv_count"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:gravity="center"android:textColor="@color/black"android:textSize="17sp"tools:text="2"/><TextViewandroid:id="@+id/tv_price"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:gravity="right|center"android:textColor="@color/black"android:textSize="15sp"tools:text="1000"/><TextViewandroid:id="@+id/tv_sum"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1.2"android:gravity="right|center"android:textColor="@color/red"android:textSize="17sp"tools:text="2000"/></LinearLayout>

货物清单数据布局文件

item_goods.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:id="@+id/ll_item"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center"android:background="@color/white"android:gravity="center"android:orientation="vertical"><TextViewandroid:id="@+id/tv_name"android:layout_width="match_parent"android:layout_height="wrap_content"android:gravity="center"android:textColor="@color/black"android:textSize="17sp"tools:text="小米手机" /><ImageViewandroid:id="@+id/iv_thumb"android:layout_width="180dp"android:layout_height="150dp"android:scaleType="fitCenter"tools:src="@drawable/xiaomi" /><LinearLayoutandroid:layout_width="match_parent"android:layout_height="45dp"android:orientation="horizontal"><TextViewandroid:id="@+id/tv_price"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="2"android:gravity="center"android:textColor="@color/red"android:textSize="15sp"tools:text="20" /><Buttonandroid:id="@+id/btn_add"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="3"android:gravity="center"android:text="加入购物车"android:textColor="@color/black"android:textSize="15sp" /></LinearLayout></LinearLayout>

顶部布局文件

title_shopping.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="50dp"android:background="#aaaaff" ><ImageViewandroid:id="@+id/iv_back"android:layout_width="50dp"android:layout_height="match_parent"android:layout_alignParentLeft="true"android:padding="10dp"android:scaleType="fitCenter"android:src="@drawable/ic_back" /><TextViewandroid:id="@+id/tv_title"android:layout_width="wrap_content"android:layout_height="match_parent"android:layout_centerInParent="true"android:gravity="center"android:textColor="@color/black"android:textSize="20sp" /><ImageViewandroid:id="@+id/iv_cart"android:layout_width="50dp"android:layout_height="match_parent"android:layout_alignParentRight="true"android:scaleType="fitCenter"android:src="@drawable/cart" /><TextViewandroid:id="@+id/tv_count"android:layout_width="20dp"android:layout_height="20dp"android:layout_alignParentTop="true"android:layout_toRightOf="@+id/iv_cart"android:layout_marginLeft="-20dp"android:gravity="center"android:background="@drawable/shape_oval_red"android:text="0"android:textColor="@color/white"android:textSize="15sp" /></RelativeLayout>

资源文件

shape_oval_red.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"android:shape="oval"><solid android:color="#ff6666" /></shape>

colors.xml

<?xml version="1.0" encoding="utf-8"?>
<resources><color name="purple_200">#FFBB86FC</color><color name="purple_500">#FF6200EE</color><color name="purple_700">#FF3700B3</color><color name="teal_200">#FF03DAC5</color><color name="teal_700">#FF018786</color><color name="black">#FF000000</color><color name="white">#FFFFFFFF</color><color name="grey">#cccccc</color><color name="orange">#ffffdd</color><color name="red">#ff0000</color>
</resources>

AndroidManifest.xml

把自己写的MyApplication配置上

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"package="com.kcs.shoppingcart"><applicationandroid:name=".MyApplication"android:allowBackup="true"android:icon="@mipmap/ic_launcher"android:label="@string/app_name"android:roundIcon="@mipmap/ic_launcher_round"android:supportsRtl="true"android:theme="@style/Theme.ShoppingCart"><activityandroid:name=".ShoppingCartActivity"android:exported="true" /><activityandroid:name=".ShoppingDetailActivity"android:exported="true" /><activityandroid:name=".ShoppingChannelActivity"android:exported="true"><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity></application></manifest>

Android -- 购物车相关推荐

  1. android落下动画,Android应用开发android 购物车小球掉落动画

    本文将带你了解Android应用开发android 购物车小球掉落动画,希望本文对大家学Android有所帮助. 先贴效果图 对自定义View小红球的绘制 public class BallView ...

  2. android 购物车加减列表,Android 购物车加减功能的实现代码

    Android 实现购物车加减功能,效果图如下所示: public class adderView extends LinearLayout implements View.OnClickListen ...

  3. android购物车栏,Android怎么实现二级列表购物车功能

    Android怎么实现二级列表购物车功能 发布时间:2021-04-16 12:45:40 来源:亿速云 阅读:61 作者:小新 小编给大家分享一下Android怎么实现二级列表购物车功能,希望大家阅 ...

  4. Android - 购物车页面【仿】淘宝App

    首先是效果图 xml布局文件 activity_shopping.xml <RelativeLayout xmlns:android="http://schemas.android.c ...

  5. android 购物车实现,Android Studio实现简单购物车功能

    Android Studio实现简单购物车功能 发布时间:2020-08-30 17:23:56 来源:脚本之家 阅读:241 作者:攀岩嘉 本文实例为大家分享了Android九宫格图片展示的具体代码 ...

  6. android 购物车操作并发,Android 购物车页面和逻辑实现

    之前在CSDN上写了几篇..现在想在简书上也写写,所以就过来试试....嘻嘻嘻~~~好,,进入正题.... 这是之前在做的项目中的一个功能 购物车! 我这个购物车业务逻辑还算可以吧,不算太难,但由于我 ...

  7. Android 购物车UI及逻辑实现

    转自:http://blog.csdn.net/u011011744/article/details/53538972先看看效果吧! 目前我做的功能除了结算就这些了- 下面开始来看代码 Activit ...

  8. android购物车简单实现全选+加减器+总价格

    //Activity主頁面佈局 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android&qu ...

  9. android购物车代码简述,Android实现简单购物车功能

    本文实例为大家分享了Android实现购物车功能的具体代码,供大家参考,具体内容如下 MainActivity布局: android:layout_width="match_parent&q ...

最新文章

  1. 创业者具备的五大技能_一个优秀创业者必备的基本素质和技能
  2. Guava关于JAVA中系统组件之间交互通讯(非线程之间通讯)
  3. 3DSlicer12:风格准则
  4. Maven基础了解及配置信息
  5. 前端学习(2660):外部传入也行
  6. php登录个性验证码,PHP七种不同的个性创意验证码例子
  7. 各种Java加密算法
  8. 票据打印, 账单打印, 标签打印, 文档打印, 条码打印, 批量打印, 包装纸打印与设计,可变数据打印打印,发布,VC++源代码组件库解决方案...
  9. java 微信企业号上传文件_微信企业号上传下载多媒体文件接口详解演示-java
  10. @Cotroller和@RestCotroller
  11. 开源项目征集 | CSDN “开源加速器计划”之【开源技术栈选型 Show】
  12. 数学家、数学轶事与数学史话
  13. Django 数据流程图
  14. 计算机二级java难不_计算机二级java含金量如何 对就业有帮助吗
  15. SNMP-简单网络管理协议
  16. 易语言:游戏辅助 CF队伤“卡秒器“ 编程思路/开发者优化建议
  17. 解决invalid operands of types ‘float‘ and ‘int‘ to binary ‘operator %
  18. csgo原始输入开不开_CSGO职业哥参数配置:帅气猪猪JW
  19. 深度学习:GPU云服务器的租用
  20. Mac卸载程序清除残留文件

热门文章

  1. 大数据之hive:行列转换系列总结
  2. 全网都在求的「蚂蚁呀嘿」教程--基于PaddleGAN的First order motion model实现
  3. Linux三剑客用法整理
  4. wifi连接速率 linux,Deepin linux 操作系统提高 WiFi 速度
  5. 如何培养自己积极的心态-思维与习惯影响未来,积极的心态决定了成功的85%
  6. 抓取WebSocket推送的消息
  7. TeamViewer 连接问题
  8. 后端一次性传了10w条数据,前端该如何处理?—— 面试高频
  9. 甲骨文发布移动版Java发展路线图
  10. 滴滴副总裁叶杰平离职,他是出行巨头的AI掌门人