Android实现简单购物车

本文实例为大家分享了Android实现简单购物车的具体代码,供大家参考,具体内容如下

这里我用到的都是Android自带SDK中的资源,做了一个极其简单的购物车实现,总结购物车难点包含两个方面:

1、CheckBox的联动:

全选框、商铺复选框以及商品复选框要做到滴水不漏的联动,我的经验是在监听多选框时尽量采用click事件,避免使用checkChange事件(因为它总是能在你意想不到的地方调用),全选框可以通过商品价格来判断,这个在代码中也有体现。

2、数据的联动和UI的联动:

适配器的都是在外部类创建,而总价格等控件都是在调用适配器的地方,这个要做到联动,最简单的方式必然就是接口的回调,熟练使用可以节省很多代码,提高编程效率。

再有一个比较容易出现问题的地方就在于,我们经常是首先更改数据,然后通知适配器刷新数据(notifyDataSetChanged()),这里要注意的一点就是在更新数据的时候,一定确保更新的传递到适配器中的数据集合,否则会发现这个更新适配器的方法是无效的。

其他相关问题代码中均有体现,如果和我一样是一个编程小白,仔细阅读会有收获滴。

代码中没有添加自己的资源,逻辑都有实现就是UI丑了一点

activity_main:

<?xml version="1.0" encoding="utf-8"?> <LinearLayout     android:orientation="vertical"     xmlns:android="http://schemas.android.com/apk/res/android"     xmlns:tools="http://schemas.android.com/tools"     android:id="@+id/activity_main"     android:layout_width="match_parent"     android:layout_height="match_parent"     tools:context="com.bwie.test.test1025two.MainActivity">     <RelativeLayout         android:layout_gravity="center_horizontal"         android:background="@color/colorAccent"         android:layout_width="match_parent"         android:layout_height="50dp">         <TextView             android:textSize="38sp"             android:gravity="center"             android:textColor="#fff"             android:text="购物车"             android:layout_width="match_parent"             android:layout_height="wrap_content" />         <TextView             android:textColor="#fff"             android:textSize="38sp"             android:layout_alignParentRight="true"             android:text="2"             android:id="@+id/main_num"             android:layout_width="wrap_content"             android:layout_height="wrap_content" />     </RelativeLayout>     <ExpandableListView         android:layout_weight="1"         android:id="@+id/expand_able_view"         android:layout_width="match_parent"         android:layout_height="match_parent"/>     <LinearLayout         android:layout_width="match_parent"         android:layout_height="wrap_content">         <CheckBox             android:layout_weight="1"             android:id="@+id/main_check_all"             android:text="全选"             android:layout_width="0dp"             android:layout_height="wrap_content" />         <TextView             android:id="@+id/main_price"             android:gravity="center_horizontal"             android:text="0"             android:layout_weight="1"             android:layout_width="0dp"             android:layout_height="wrap_content" />         <Button             android:id="@+id/btn_delete"             android:background="#aaa"             android:layout_weight="1"             android:text="删除"             android:layout_width="0dp"             android:layout_height="wrap_content" />         <Button             android:id="@+id/btn_buy"             android:background="#f99"             android:layout_weight="1"             android:text="购买"             android:layout_width="0dp"             android:layout_height="wrap_content" />     </LinearLayout> </LinearLayout>

group_item:

注:这里图了个简单,商铺名称我是通过设置CheckBox的text来显示的,另外取消焦点是为了不影响二级列表的点击展开与收回子集列表

<?xml version="1.0" encoding="utf-8"?> <LinearLayout     android:orientation="horizontal"     xmlns:android="http://schemas.android.com/apk/res/android"     android:layout_width="match_parent"     android:layout_height="match_parent">     <CheckBox         android:focusable="false"         android:id="@+id/group_check"         android:layout_width="wrap_content"         android:layout_height="wrap_content" /> </LinearLayout>

child_item:

<?xml version="1.0" encoding="utf-8"?> <LinearLayout     android:orientation="horizontal"     xmlns:android="http://schemas.android.com/apk/res/android"     android:layout_width="match_parent"     android:layout_height="match_parent">     <CheckBox         android:id="@+id/child_check"         android:layout_width="wrap_content"         android:layout_height="wrap_content" />     <ImageView         android:id="@+id/child_img"         android:scaleType="center"         android:src="@mipmap/ic_launcher"         android:layout_width="80dp"         android:layout_height="80dp" />     <TextView         android:id="@+id/child_price"         android:textSize="22sp"         android:textColor="@color/colorPrimary"         android:text="2888"         android:layout_width="wrap_content"         android:layout_height="80dp" />     <RelativeLayout         android:layout_weight="1"         android:layout_width="match_parent"         android:layout_height="80dp">         <TextView             android:text="名字"             android:id="@+id/child_name"             android:layout_width="wrap_content"             android:layout_height="wrap_content" />         <LinearLayout             android:orientation="horizontal"             android:layout_alignParentBottom="true"             android:layout_width="wrap_content"             android:layout_height="wrap_content">             <TextView                 android:id="@+id/child_jian"                 android:gravity="center_horizontal"                 android:text="—"                 android:layout_width="30dp"                 android:layout_height="30dp" />             <TextView                 android:gravity="center_horizontal"                 android:text="2"                 android:id="@+id/child_num"                 android:layout_width="30dp"                 android:layout_height="30dp" />             <TextView                 android:id="@+id/child_jia"                 android:gravity="center_horizontal"                 android:text="+"                 android:layout_width="30dp"                 android:layout_height="30dp" />         </LinearLayout>     </RelativeLayout> </LinearLayout>

groupBean:

package com.bwie.test.test1025two; import java.util.ArrayList; /**  * Created by Zzw on 2017/10/25.  */ public class Group {     private String name;     private boolean check;     private ArrayList<Child> children;     public Group(String name, boolean check,ArrayList<Child> children) {         this.name = name;         this.check = check;         this.children = children;     }     public Group() {     }     public String getName() {         return name;     }     public void setName(String name) {         this.name = name;     }     public boolean isCheck() {         return check;     }     public void setCheck(boolean check) {         this.check = check;     }     public void setChildren(ArrayList<Child> children){         this.children = children;     }     public ArrayList<Child> getChildren(){         return children;     }     @Override     public String toString() {         return "Group{" +                 "name='" + name + '\'' +                 ", check=" + check +                 '}';     } }

childBean:

package com.bwie.test.test1025two; /**  * Created by Zzw on 2017/10/25.  */ public class Child {     private String name;     private String img;     private int num;     private boolean check;     private int price;     public Child(String name, String img, int num, boolean check, int price) {         this.name = name;         this.img = img;         this.num = num;         this.check = check;         this.price = price;     }     public Child() {     }     public String getName() {         return name;     }     public void setName(String name) {         this.name = name;     }     public String getImg() {         return img;     }     public void setImg(String img) {         this.img = img;     }     public int getNum() {         return num;     }     public void setNum(int num) {         this.num = num;     }     public boolean isCheck() {         return check;     }     public void setCheck(boolean check) {         this.check = check;     }     public int getPrice() {         return price;     }     public void setPrice(int price) {         this.price = price;     }     @Override     public String toString() {         return "Child{" +                 "name='" + name + '\'' +                 ", img='" + img + '\'' +                 ", num=" + num +                 ", check=" + check +                 ", price=" + price +                 '}';     } }

MyAdapter:

package com.bwie.test.test1025two; import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseExpandableListAdapter; import android.widget.CheckBox; import android.widget.ImageView; import android.widget.TextView; import java.util.ArrayList; /**  * Created by Zzw on 2017/10/25.  */ public class MyAdapter extends BaseExpandableListAdapter {     Context context;     ArrayList<Group> groups;     public MyAdapter(Context context, ArrayList<Group> groups) {         this.context = context;         this.groups = groups;     }     //监听加减事件回调接口     public interface onNumChangeListener{         void onNumChange(int groupID,int childID,boolean isAdd);     }     private onNumChangeListener mOnNumChangeListener;     public void setOnNumChangeListener(onNumChangeListener mOnNumChangeListener){         this.mOnNumChangeListener = mOnNumChangeListener;     }     //监听多选框点击事件回调接口。     public interface onCheckChangeListener{         void onGroupClick(int groupID);         void onChildClick(int groupID,int childID);     }     private onCheckChangeListener mOnCheckChangeListener;     public void setmOnCheckChangeListener(onCheckChangeListener mOnCheckChangeListener){         this.mOnCheckChangeListener = mOnCheckChangeListener;     }     //监听价格需要更新回调接口     public interface onShouldChangeMoneyListener{         void onShouldChnageMoney();     }     private onShouldChangeMoneyListener mOnShouldChangeMoneyListener;     public void setmOnShouldChangeMoneyListener(onShouldChangeMoneyListener mOnShouldChangeMoneyListener){         this.mOnShouldChangeMoneyListener = mOnShouldChangeMoneyListener;     }     @Override     public int getGroupCount() {         return groups.size();     }     @Override     public int getChildrenCount(int i) {         return groups.get(i).getChildren().size();     }     @Override     public Object getGroup(int i) {         return groups.get(i);     }     @Override     public Object getChild(int i, int i1) {         return groups.get(i).getChildren().get(i1);     }     @Override     public long getGroupId(int i) {         return i;     }     @Override     public long getChildId(int i, int i1) {         return i1;     }     @Override     public boolean hasStableIds() {         return false;     }     @Override     public View getGroupView(final int i, boolean b, View view, ViewGroup viewGroup) {         GroupHolder holder = null;         if (view == null){             view = LayoutInflater.from(context).inflate(R.layout.group_item,viewGroup,false);             holder  = new GroupHolder();             holder.checkBox = (CheckBox) view.findViewById(R.id.group_check);             view.setTag(holder);         }else{             holder = (GroupHolder) view.getTag();         }         holder.checkBox.setText(groups.get(i).getName());         holder.checkBox.setChecked(groups.get(i).isCheck());         if (mOnCheckChangeListener != null&&mOnShouldChangeMoneyListener != null){             holder.checkBox.setOnClickListener(new View.OnClickListener() {                 @Override                 public void onClick(View view) {                     mOnCheckChangeListener.onGroupClick(i);                     mOnShouldChangeMoneyListener.onShouldChnageMoney();                 }             });         }         return view;     }     @Override     public View getChildView(final int i,final int i1, boolean b, View view, ViewGroup viewGroup) {         ChildHolder holder = null;         if (view == null){             view = LayoutInflater.from(context).inflate(R.layout.child_item,viewGroup,false);             holder = new ChildHolder();             holder.checkBox = (CheckBox) view.findViewById(R.id.child_check);             holder.imageView = (ImageView) view.findViewById(R.id.child_img);             holder.name = (TextView) view.findViewById(R.id.child_name);             holder.num = (TextView) view.findViewById(R.id.child_num);             holder.jian = (TextView) view.findViewById(R.id.child_jian);             holder.jia = (TextView) view.findViewById(R.id.child_jia);             holder.price = (TextView) view.findViewById(R.id.child_price);             view.setTag(holder);         }else{             holder = (ChildHolder) view.getTag();         }         holder.checkBox.setChecked(groups.get(i).getChildren().get(i1).isCheck());         holder.imageView.setImageResource(R.mipmap.ic_launcher);         holder.name.setText(groups.get(i).getChildren().get(i1).getName());         holder.num.setText(groups.get(i).getChildren().get(i1).getNum()+"");         holder.price.setText(groups.get(i).getChildren().get(i1).getPrice()+"");         if (mOnNumChangeListener != null&&mOnShouldChangeMoneyListener != null){             holder.jian.setOnClickListener(new View.OnClickListener() {                 @Override                 public void onClick(View view) {                     mOnNumChangeListener.onNumChange(i,i1,false);                     mOnShouldChangeMoneyListener.onShouldChnageMoney();                 }             });         }         if (mOnNumChangeListener != null&&mOnShouldChangeMoneyListener != null){             holder.jia.setOnClickListener(new View.OnClickListener() {                 @Override                 public void onClick(View view) {                     mOnNumChangeListener.onNumChange(i,i1,true);                     mOnShouldChangeMoneyListener.onShouldChnageMoney();                 }             });         }         if (mOnCheckChangeListener != null&&mOnShouldChangeMoneyListener != null){             holder.checkBox.setOnClickListener(new View.OnClickListener() {                 @Override                 public void onClick(View view) {                     mOnCheckChangeListener.onChildClick(i,i1);                     mOnShouldChangeMoneyListener.onShouldChnageMoney();                 }             });         }         return view;     }     @Override     public boolean isChildSelectable(int i, int i1) {         return true;     }     class GroupHolder {         CheckBox checkBox;     }     class ChildHolder{         CheckBox checkBox;         ImageView imageView;         TextView name,num,jian,jia,price;     } }

MainActivity:

package com.bwie.test.test1025two; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.view.View; import android.widget.Button; import android.widget.CheckBox; import android.widget.ExpandableListView; import android.widget.TextView; import android.widget.Toast; import java.util.ArrayList; import java.util.List; public class MainActivity extends AppCompatActivity {     TextView num,price;//右上角当前商品数量和底部当前已选中商品的价格     ExpandableListView expandableListView;//展示商品信息的二级列表     CheckBox checkAll;//左下角全选     Button btnDel,btnBuy;//底部删除当前选中按钮、购买按钮     ArrayList<Group> groups = new ArrayList<>();//数据源集合     MyAdapter adapter;//自定义baseExpandable适配器     @Override     protected void onCreate(Bundle savedInstanceState) {         super.onCreate(savedInstanceState);         setContentView(R.layout.activity_main);         initView();//控件初始化         initData();//数据初始化         changeGoodsNum();//初始化当前商品个数。         /**          * 自定义加减按钮回调          * params: groupID:商铺id  childID:商品在当前商铺的id isADD:非加即减          */         adapter.setOnNumChangeListener(new MyAdapter.onNumChangeListener() {             @Override             public void onNumChange(int groupID, int childID, boolean isAdd) {                 //获得当前点击商品的数量                 int num = groups.get(groupID).getChildren().get(childID).getNum();                 if (isAdd){//加                     //在数据源中该商品数量自增1                     groups.get(groupID).getChildren().get(childID).setNum(++num);                 }else{//减                     if (num == 1){//数量为1给出提示                         Toast.makeText(MainActivity.this, "受不了了,不能再少了", Toast.LENGTH_SHORT).show();                     }else{//在数据源中该商品数量自减1                         groups.get(groupID).getChildren().get(childID).setNum(--num);                     }                 }                 //更新UI                 adapter.notifyDataSetChanged();                 changeMoney();//更新价格显示             }         });         //自定义商铺和商品多选框点击回调         adapter.setmOnCheckChangeListener(new MyAdapter.onCheckChangeListener() {             @Override             public void onGroupClick(int groupID) {//组点击                 //将数据源置反,以保持同步                 groups.get(groupID).setCheck(!(groups.get(groupID).isCheck()));                 //获取当前选中状态                 boolean flag = groups.get(groupID).isCheck();                 //更新其下所有商品CheckBox                 for (int i = 0 ; i < groups.get(groupID).getChildren().size(); i++){                     groups.get(groupID).getChildren().get(i).setCheck(flag);                 }                 //更新UI                 adapter.notifyDataSetChanged();                 //更新价格显示                 changeMoney();             }             @Override             public void onChildClick(int groupID, int childID) {//商品点击                 //将数据源置反以保持同步                 groups.get(groupID).getChildren().get(childID).setCheck(!(groups.get(groupID).getChildren().get(childID).isCheck()));                 //判断该条目及所有兄弟条目是否全部选中,以及时更新商铺CheckBox                 int flag = 0;                 for (int i = 0 ; i < groups.get(groupID).getChildren().size() ; i++){                     if (groups.get(groupID).getChildren().get(i).isCheck()){                         flag++;                     }                 }                 //如果该组下的选中数量与该集合长度相等,说明全部选中,更新组CheckBox                 if (flag == groups.get(groupID).getChildren().size()){                     groups.get(groupID).setCheck(true);                 }else{                     groups.get(groupID).setCheck(false);                 }                 //更新UI                 adapter.notifyDataSetChanged();                 //更新价格显示                 changeMoney();             }         });         //删除按钮点击         btnDel.setOnClickListener(new View.OnClickListener() {             @Override             public void onClick(View view) {                 List<Group> toBeDeleteGroups = new ArrayList<Group>();// 待删除的组元素列表                 for (int i = 0; i < groups.size(); i++) {                     Group group = groups.get(i);                     if (group.isCheck()) {                         toBeDeleteGroups.add(group);                     }                     List<Child> toBeDeleteChildren = new ArrayList<Child>();// 待删除的子元素列表                     List<Child> childs = group.getChildren();                     for (int j = 0; j < childs.size(); j++) {                         if (childs.get(j).isCheck()) {                             toBeDeleteChildren.add(childs.get(j));                         }                     }                     childs.removeAll(toBeDeleteChildren);                 }                 groups.removeAll(toBeDeleteGroups);                 //更新UI                 adapter.notifyDataSetChanged();                 //更新当前商品数量显示                 changeGoodsNum();                 //更新当前价格显示                 changeMoney();             }         });         //购买按钮,点击提示当前选中金额         btnBuy.setOnClickListener(new View.OnClickListener() {             @Override             public void onClick(View view) {                 String money = price.getText().toString();                 Toast.makeText(MainActivity.this, "当前总金额:"+money, Toast.LENGTH_SHORT).show();             }         });         //全选按钮,点击更新视图所有CheckBox         checkAll.setOnClickListener(new View.OnClickListener() {             @Override             public void onClick(View view) {                 for (int i = 0 ; i< groups.size() ; i++){                     groups.get(i).setCheck(checkAll.isChecked());                     for (int j = 0 ; j < groups.get(i).getChildren().size() ; j ++){                         groups.get(i).getChildren().get(j).setCheck(checkAll.isChecked());                     }                 }                 //更新UI                 adapter.notifyDataSetChanged();                 //更新总价显示                 changeMoney();             }         });         //自定义回调更新总价         adapter.setmOnShouldChangeMoneyListener(new MyAdapter.onShouldChangeMoneyListener() {             @Override             public void onShouldChnageMoney() {                 //更新总价显示                 changeMoney();             }         });     }     //初始化数据,设置适配器     private void initData() {         for (int i = 0 ; i < 5 ; i++){             ArrayList<Child> children = new ArrayList<>();             for (int j = 0 ; j <= i ; j++){                 children.add(new Child("店铺"+i+"的商品:"+j,"",2,false,j+1));             }             groups.add(new Group("商铺:"+i,false,children));         }         adapter = new MyAdapter(this,groups);         expandableListView.setAdapter(adapter);         for (int i = 0; i < groups.size(); i++)         {             expandableListView.expandGroup(i);// 初始化时,将ExpandableListView以展开的方式呈现         }     }     //获得控件资源     private void initView() {         num = (TextView) findViewById(R.id.main_num);         expandableListView = (ExpandableListView) findViewById(R.id.expand_able_view);         checkAll = (CheckBox) findViewById(R.id.main_check_all);         btnDel = (Button) findViewById(R.id.btn_delete);         btnBuy = (Button) findViewById(R.id.btn_buy);         price = (TextView) findViewById(R.id.main_price);     }     //当前购物车商品数量     private void changeGoodsNum(){         int currentNum = 0;         for (int i = 0 ; i < groups.size(); i++){             for (int j = 0 ; j < groups.get(i).getChildren().size(); j++){                 currentNum++;             }         }         num.setText(currentNum+"");     }     //更新总价     private void changeMoney(){         int money = 0;         int allMoney = 0;//获得当前全部商品价格         for (int i = 0 ; i < groups.size(); i++){             for (int j = 0 ; j < groups.get(i).getChildren().size(); j++){                 if (groups.get(i).getChildren().get(j).isCheck()){                     money += groups.get(i).getChildren().get(j).getNum() * groups.get(i).getChildren().get(j).getPrice();                 }                 allMoney += groups.get(i).getChildren().get(j).getNum() * groups.get(i).getChildren().get(j).getPrice();             }         }         //当选中价格与全部价格相等,更新全选框         if (money == allMoney){             checkAll.setChecked(true);         }else{             checkAll.setChecked(false);         }         price.setText(money + "");     } }

效果图:

推荐阅读