Android 购物车页面和逻辑实现
2016-12-09 14:57
381 查看
距离上次写第一篇博客已经好久了,今天正好有时间就来写一篇关于最近在做的项目中的一个功能 购物车! 我这个购物车业务逻辑还算可以吧,不算太难,但由于我是第一次做,所以也碰到了很多细节上的问题...所以我想总结下来,方便以后学习和使用..好了先看看效果吧!
目前我做的功能除了结算就这些了...
下面开始来看代码
Activity界面是这样的
首先是Activity 布局xml
item 布局xml
由于很多操作是在Activity中操作 ListView的item ,所以我这里选择的是接口回调,我感觉方便些..也许你会有更好的方法.
首先我们在 Adapter中定义了几个
再来看看Adapter 没啥可说的.. 注释我在代码写的还算详细 ,相信能看懂
现在我们在来看看Activity 代码, 同样注释写的很详细
整体的就是这样,,我说一下 我做的时候遇到的问题和解决办法
1.
问题:当我单选一个一个选中后,全选按钮也会自动选中 ,但是当我取消一个item后 全选按钮没有自动取消 (正常是只有有一个item没有选中 全选按钮是不会选中的)
解决:首先解决问题要找到原因所在 ,造成这个Bug的原因是我CheckBox的点击事件用的是setOnCheckedChangeListener 后来换成了setOnClickListener 就好了 .
两者都能实现对CheckBox的状态改变的监听,但一般情况下,用的更多的是setOnCheckedChangeListener。因为,当CheckBox的状态不是通过点击事件改变,而是通过其他的方式改变时,比如setCheck(),setOnClickListener无法完成此种情况下的监听。OnCheckChangedListener监听CheckBox的状态,无论来自你的onClick事件还是其他。
2.
问题: 就是在改变物品个数的是时候会出现复用!
解决: 原因就是我没有保存当前 改变后是值, 保存一下就OK了..
总体上就是这些了.......感兴趣的同学可以下载demo看看
Demo在这里----->http://download.csdn.net/detail/u011011744/9706870
目前我做的功能除了结算就这些了...
下面开始来看代码
Activity界面是这样的
首先是Activity 布局xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <include android:id="@+id/shopping_title" layout="@layout/layout_title" /> <TextView android:id="@+id/tv_edit" android:layout_width="wrap_content" android:layout_height="25dp" android:layout_gravity="right" android:layout_margin="10dp" android:text="编辑" android:textSize="18dp" /> <View android:layout_width="match_parent" android:layout_height="1dp" android:layout_below="@id/tv_edit" android:background="@color/gray3" /> <ListView android:id="@+id/list_shopping_cart" android:layout_width="match_parent" android:layout_height="0dp" android:layout_below="@id/tv_edit" android:layout_weight="1" android:scrollbars="none" /> <View android:layout_width="match_parent" android:layout_height="1dp" android:background="@color/gray3" /> <RelativeLayout android:id="@+id/rl_bottom" android:layout_width="match_parent" android:layout_height="50dp" android:layout_alignParentBottom="true" android:background="@color/white"> <CheckBox android:id="@+id/ck_all" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_centerVertical="true" android:button="@drawable/check_box_style" android:checkMark="?android:attr/listChoiceIndicatorMultiple" android:gravity="center" android:paddingLeft="10dp" android:scaleX="0.6" android:scaleY="0.6" android:text="全选" android:textAppearance="?android:attr/textAppearanceLarge" android:textColor="@color/desccolor" /> <TextView android:id="@+id/tv_settlement" android:layout_width="80dp" android:layout_height="match_parent" android:layout_alignParentRight="true" android:background="@color/desccolor" android:gravity="center" android:text="结算(0)" android:textColor="@color/white" /> <TextView android:id="@+id/tv_show_price" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_toLeftOf="@id/tv_settlement" android:gravity="center" android:padding="5dp" android:text="合计:0.00" android:textColor="@color/desccolor" /> </RelativeLayout> </LinearLayout>再来看 ListView item的布局
item 布局xml
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="190dp" android:orientation="vertical"> <CheckBox android:id="@+id/ck_chose" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerVertical="true" android:layout_marginLeft="8dp" android:button="@drawable/check_box_style" android:scaleX="0.6" android:scaleY="0.6" /> <ImageView android:id="@+id/iv_show_pic" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerVertical="true" android:layout_marginLeft="10dp" android:layout_toRightOf="@id/ck_chose" android:background="@mipmap/demo" /> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="15dp" android:layout_marginTop="30dp" android:layout_toRightOf="@id/iv_show_pic" android:orientation="vertical"> <TextView android:id="@+id/tv_commodity_name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="酒红色纯红色纯羊毛西服套装" android:textColor="@color/black" android:textStyle="bold" /> <RelativeLayout android:id="@+id/rl_edit" android:layout_width="110dp" android:layout_height="30dp" android:orientation="horizontal" android:visibility="gone"> <ImageView android:id="@+id/iv_sub" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@mipmap/iv_sub" /> <TextView android:id="@+id/tv_show_num" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_centerVertical="true" android:text="1" android:textColor="@color/desccolor" /> <ImageView android:id="@+id/iv_add" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:background="@mipmap/iv_add" /> <View android:layout_width="match_parent" android:layout_height="0.7dp" android:layout_alignParentBottom="true" android:background="@color/black" /> </RelativeLayout> <TextView android:id="@+id/tv_fabric" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="10dp" android:text="面料:" android:textColor="@color/gray5" /> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal"> <TextView android:id="@+id/tv_dress" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="10dp" android:text="西服尺寸: 48" android:textColor="@color/gray5" /> </LinearLayout> <TextView android:id="@+id/tv_pants" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="10dp" android:text="西裤尺寸: 68" android:textColor="@color/gray5" /> <LinearLayout android:layout_width="wrap_content" android:layout_h f09a eight="wrap_content" android:layout_marginTop="10dp" android:orientation="horizontal"> <TextView android:id="@+id/tv_price" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="¥390" android:textColor="@color/black" android:textStyle="bold" /> <TextView android:id="@+id/tv_num" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="40dp" android:text="x1" android:textColor="@color/gray5" /> </LinearLayout> </LinearLayout> <TextView android:id="@+id/tv_delete" android:layout_width="60dp" android:layout_height="match_parent" android:layout_alignParentRight="true" android:background="@color/address_press" android:gravity="center" android:text="删除" android:visibility="gone" /> </RelativeLayout>好了 ,,布局就说完了 现在我们来看看逻辑部分
由于很多操作是在Activity中操作 ListView的item ,所以我这里选择的是接口回调,我感觉方便些..也许你会有更好的方法.
首先我们在 Adapter中定义了几个
/** * 复选框接口 */ public interface CheckInterface { /** * 组选框状态改变触发的事件 * * @param position 元素位置 * @param isChecked 元素选中与否 */ void checkGroup(int position, boolean isChecked); } /** * 改变数量的接口 */ public interface ModifyCountInterface { /** * 增加操作 * * @param position 组元素位置 * @param showCountView 用于展示变化后数量的View * @param isChecked 子元素选中与否 */ void doIncrease(int position, View showCountView, boolean isChecked); /** * 删减操作 * * @param position 组元素位置 * @param showCountView 用于展示变化后数量的View * @param isChecked 子元素选中与否 */ void doDecrease(int position, View showCountView, boolean isChecked); /** * 删除子item * * @param position */ void childDelete(int position); }
再来看看Adapter 没啥可说的.. 注释我在代码写的还算详细 ,相信能看懂
public class ShoppingCartAdapter extends BaseAdapter { private boolean isShow = true;//是否显示编辑/完成 private List<ShoppingCartBean> shoppingCartBeanList; private CheckInterface checkInterface; private ModifyCountInterface modifyCountInterface; private Context context; public ShoppingCartAdapter(Context context) { this.context = context; } public void setShoppingCartBeanList(List<ShoppingCartBean> shoppingCartBeanList) { this.shoppingCartBeanList = shoppingCartBeanList; notifyDataSetChanged(); } /** * 单选接口 * * @param checkInterface */ public void setCheckInterface(CheckInterface checkInterface) { this.checkInterface = checkInterface; } /** * 改变商品数量接口 * * @param modifyCountInterface */ public void setModifyCountInterface(ModifyCountInterface modifyCountInterface) { this.modifyCountInterface = modifyCountInterface; } @Override public int getCount() { return shoppingCartBeanList == null ? 0 : shoppingCartBeanList.size(); } @Override public Object getItem(int position) { return shoppingCartBeanList.get(position); } @Override public long getItemId(int position) { return position; } /** * 是否显示可编辑 * * @param flag */ public void isShow(boolean flag) { isShow = flag; notifyDataSetChanged(); } @Override public View getView(final int position, View convertView, ViewGroup parent) { final ViewHolder holder; if (convertView == null) { convertView = LayoutInflater.from(context).inflate(R.layout.item_shopping_cart_layout, parent, false); holder = new ViewHolder(convertView); convertView.setTag(holder); } else { holder = (ViewHolder) convertView.getTag(); } final ShoppingCartBean shoppingCartBean = shoppingCartBeanList.get(position); holder.tv_commodity_name.setText(shoppingCartBean.getShoppingName()); holder.tv_fabric.setText("面料:" + shoppingCartBean.getFabric()); holder.tv_dress.setText("西服尺寸:" + shoppingCartBean.getDressSize()); holder.tv_pants.setText("西裤尺寸:" + shoppingCartBean.getPantsSize()); holder.tv_price.setText("¥:" + shoppingCartBean.getPrice()); holder.ck_chose.setChecked(shoppingCartBean.isChoosed()); holder.tv_show_num.setText(shoppingCartBean.getCount() + ""); holder.tv_num.setText("X" + shoppingCartBean.getCount()); //单选框按钮 holder.ck_chose.setOnClickListener( new View.OnClickListener() { @Override public void onClick(View v) { shoppingCartBean.setChoosed(((CheckBox) v).isChecked()); checkInterface.checkGroup(position, ((CheckBox) v).isChecked());//向外暴露接口 } } ); //增加按钮 holder.iv_add.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { modifyCountInterface.doIncrease(position, holder.tv_show_num, holder.ck_chose.isChecked());//暴露增加接口 } }); //删减按钮 holder.iv_sub.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { modifyCountInterface.doDecrease(position, holder.tv_show_num, holder.ck_chose.isChecked());//暴露删减接口 } }); //删除弹窗 holder.tv_delete.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { AlertDialog alert = new AlertDialog.Builder(context).create(); alert.setTitle("操作提示"); alert.setMessage("您确定要将这些商品从购物车中移除吗?"); alert.setButton(DialogInterface.BUTTON_NEGATIVE, "取消", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { return; } }); alert.setButton(DialogInterface.BUTTON_POSITIVE, "确定", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { modifyCountInterface.childDelete(position);//删除 目前只是从item中移除 } }); alert.show(); } }); //判断是否在编辑状态下 if (isShow) { holder.tv_commodity_name.setVisibility(View.VISIBLE); holder.tv_fabric.setVisibility(View.VISIBLE); holder.rl_edit.setVisibility(View.GONE); holder.tv_delete.setVisibility(View.GONE); } else { holder.tv_commodity_name.setVisibility(View.GONE); holder.tv_fabric.setVisibility(View.GONE); holder.rl_edit.setVisibility(View.VISIBLE); holder.tv_delete.setVisibility(View.VISIBLE); } return convertView; } //初始化控件 class ViewHolder { ImageView iv_chose; ImageView iv_show_pic, iv_sub, iv_add; TextView tv_commodity_name, tv_fabric, tv_dress, tv_pants, tv_price, tv_num, tv_delete, tv_show_num; CheckBox ck_chose; RelativeLayout rl_edit; public ViewHolder(View itemView) { ck_chose = (CheckBox) itemView.findViewById(R.id.ck_chose); iv_show_pic = (ImageView) itemView.findViewById(R.id.iv_show_pic); iv_sub = (ImageView) itemView.findViewById(R.id.iv_sub); iv_add = (ImageView) itemView.findViewById(R.id.iv_add); tv_commodity_name = (TextView) itemView.findViewById(R.id.tv_commodity_name); tv_fabric = (TextView) itemView.findViewById(R.id.tv_fabric); tv_dress = (TextView) itemView.findViewById(R.id.tv_dress); tv_pants = (TextView) itemView.findViewById(R.id.tv_pants); tv_price = (TextView) itemView.findViewById(R.id.tv_price); tv_num = (TextView) itemView.findViewById(R.id.tv_num); tv_delete = (TextView) itemView.findViewById(R.id.tv_delete); tv_show_num = (TextView) itemView.findViewById(R.id.tv_show_num); rl_edit = (RelativeLayout) itemView.findViewById(R.id.rl_edit); } }
现在我们在来看看Activity 代码, 同样注释写的很详细
public class ShoppingCartActivity extends BaseActivity implements View.OnClickListener , ShoppingCartAdapter.CheckInterface, ShoppingCartAdapter.ModifyCountInterface { public TextView tv_title, tv_settlement, tv_show_price; private TextView tv_all_check; private CheckBox ck_all; private ListView list_shopping_cart; private ShoppingCartAdapter shoppingCartAdapter; private TextView tv_edit; private boolean flag = false; private List<ShoppingCartBean> shoppingCartBeanList = new ArrayList<>(); private boolean mSelect; private double totalPrice = 0.00;// 购买的商品总价 private int totalCount = 0;// 购买的商品总数量 /** * 批量模式下,用来记录当前选中状态 */ private SparseArray<Boolean> mSelectState = new SparseArray<Boolean>(); @Override protected int getLayout() { return R.layout.layout_shopping_cart_activity; } @Override protected void initView() { tv_title = bindView(R.id.tv_title); tv_title.setText("购物车"); list_shopping_cart = bindView(R.id.list_shopping_cart); // list_shopping_cart.setOnItemClickListener(this); ck_all = bindView(R.id.ck_all); ck_all.setOnClickListener(this); // ck_all.setOnCheckedChangeListener(this); tv_show_price = bindView(R.id.tv_show_price); tv_settlement = bindView(R.id.tv_settlement); tv_settlement.setOnClickListener(this); tv_edit = bindView(R.id.tv_edit); tv_edit.setOnClickListener(this); shoppingCartAdapter = new ShoppingCartAdapter(this); shoppingCartAdapter.setCheckInterface(this); shoppingCartAdapter.setModifyCountInterface(this); list_shopping_cart.setAdapter(shoppingCartAdapter); shoppingCartAdapter.setShoppingCartBeanList(shoppingCartBeanList); } @Override protected void initData() { for (int i = 0; i < 6; i++) { ShoppingCartBean shoppingCartBean = new ShoppingCartBean(); shoppingCartBean.setShoppingName("高端大气上档次的T桖"); shoppingCartBean.setFabric("纯棉"); shoppingCartBean.setDressSize(48); shoppingCartBean.setPantsSize(65); shoppingCartBean.setPrice(60); shoppingCartBean.setCount(2); shoppingCartBeanList.add(shoppingCartBean); } } @Override public void onClick(View v) { switch (v.getId()) { //全选按钮 case R.id.ck_all: if (shoppingCartBeanList.size() != 0) { if (ck_all.isChecked()) { for (int i = 0; i < shoppingCartBeanList.size(); i++) { shoppingCartBeanList.get(i).setChoosed(true); } shoppingCartAdapter.notifyDataSetChanged(); } else { for (int i = 0; i < shoppingCartBeanList.size(); i++) { shoppingCartBeanList.get(i).setChoosed(false); } shoppingCartAdapter.notifyDataSetChanged(); } } statistics(); break; case R.id.tv_edit: flag = !flag; if (flag) { tv_edit.setText("完成"); shoppingCartAdapter.isShow(false); } else { tv_edit.setText("编辑"); shoppingCartAdapter.isShow(true); } break; } } /** * 单选 * * @param position 组元素位置 * @param isChecked 组元素选中与否 */ @Override public void checkGroup(int position, boolean isChecked) { shoppingCartBeanList.get(position).setChoosed(isChecked); if (isAllCheck()) ck_all.setChecked(true); else ck_all.setChecked(false); shoppingCartAdapter.notifyDataSetChanged(); statistics(); } /** * 遍历list集合 * * @return */ private boolean isAllCheck() { for (ShoppingCartBean group : shoppingCartBeanList) { if (!group.isChoosed()) return false; } return true; } /** * 统计操作 * 1.先清空全局计数器<br> * 2.遍历所有子元素,只要是被选中状态的,就进行相关的计算操作 * 3.给底部的textView进行数据填充 */ public void statistics() { totalCount = 0; totalPrice = 0.00; for (int i = 0; i < shoppingCartBeanList.size(); i++) { ShoppingCartBean shoppingCartBean = shoppingCartBeanList.get(i); if (shoppingCartBean.isChoosed()) { totalCount++; totalPrice += shoppingCartBean.getPrice() * shoppingCartBean.getCount(); } } tv_show_price.setText("合计:" + totalPrice); tv_settlement.setText("结算(" + totalCount + ")"); } /** * 增加 * * @param position 组元素位置 * @param showCountView 用于展示变化后数量的View * @param isChecked 子元素选中与否 */ @Override public void doIncrease(int position, View showCountView, boolean isChecked) { ShoppingCartBean shoppingCartBean = shoppingCartBeanList.get(position); int currentCount = shoppingCartBean.getCount(); currentCount++; shoppingCartBean.setCount(currentCount); ((TextView) showCountView).setText(currentCount + ""); shoppingCartAdapter.notifyDataSetChanged(); statistics(); } /** * 删减 * * @param position 组元素位置 * @param showCountView 用于展示变化后数量的View * @param isChecked 子元素选中与否 */ @Override public void doDecrease(int position, View showCountView, boolean isChecked) { ShoppingCartBean shoppingCartBean = shoppingCartBeanList.get(position); int currentCount = shoppingCartBean.getCount(); if (currentCount == 1) { return; } currentCount--; shoppingCartBean.setCount(currentCount); ((TextView) showCountView).setText(currentCount + ""); shoppingCartAdapter.notifyDataSetChanged(); statistics(); } /** * 删除 * * @param position */ @Override public void childDelete(int position) { shoppingCartBeanList.remove(position); shoppingCartAdapter.notifyDataSetChanged(); statistics(); } }
整体的就是这样,,我说一下 我做的时候遇到的问题和解决办法
1.
问题:当我单选一个一个选中后,全选按钮也会自动选中 ,但是当我取消一个item后 全选按钮没有自动取消 (正常是只有有一个item没有选中 全选按钮是不会选中的)
解决:首先解决问题要找到原因所在 ,造成这个Bug的原因是我CheckBox的点击事件用的是setOnCheckedChangeListener 后来换成了setOnClickListener 就好了 .
两者都能实现对CheckBox的状态改变的监听,但一般情况下,用的更多的是setOnCheckedChangeListener。因为,当CheckBox的状态不是通过点击事件改变,而是通过其他的方式改变时,比如setCheck(),setOnClickListener无法完成此种情况下的监听。OnCheckChangedListener监听CheckBox的状态,无论来自你的onClick事件还是其他。
2.
问题: 就是在改变物品个数的是时候会出现复用!
解决: 原因就是我没有保存当前 改变后是值, 保存一下就OK了..
总体上就是这些了.......感兴趣的同学可以下载demo看看
Demo在这里----->http://download.csdn.net/detail/u011011744/9706870
相关文章推荐
- Android 购物车页面和逻辑实现
- Android 购物车UI及逻辑实现
- android购物车逻辑的多种实现
- 详解Android实现购物车页面及购物车效果(点击动画)
- Android中实现淘宝购物车RecyclerView或LIstView的嵌套选择的逻辑
- Android实现购物车页面及购物车效果(点击动画)
- Android实现购物车逻辑
- Android 双RecyclerView嵌套实现购物车逻辑
- Android: 如何利用Handler处理和发送消息来实现页面刷新的功能
- android实现页面下方的Tab效果
- android:如果手机安装了app则打开一个activity,如果没有安装则去到android market如何在HTML页面实现
- android中一个activity实现多个xml页面互换。
- android 实现页面左右滑动
- android Gallery实现异步加载网络图片 并只加载当前停止页面图
- Android ViewPager 实现多个页面切换滑动
- [置顶] android页面管理器。可以实现完整退出android软件
- [置顶] android页面管理器。可以实现完整退出android软件
- android UI进阶之用ViewPager实现欢迎引导页面
- Magento——利用购物车促销规则(Shopping Cart Price Rules)实现自己的功能第二章: 购物车页面判断设置的规则和动作
- (Touch Android) 新浪微博Android客户端开发第一篇:Logo 页面的实现