Android-购物车+实现机制+详细讲解

购物车实现机制:

  1. 使用二级列表展示数据
  2. 设置全选全不选以及父条目子条目联动的效果
  3. 实现加减数量的改变
  4. 计算总价并更新

详细讲解:

  • 使用控件ExpandableListView来展示二级列表数据
  • 创建类继承BaseExpandableListAdapter来写适配器的操作
  • 使用自定义view组合控件实现加减和数量显示的效果
  • 子条目和父条目都设置CheckBox
  • 实现CheckBox关联(这里需要一些稍微复杂的逻辑操作)
    1.当父条目选中那么此父条目相对应的子条目也要选中
    2.当子条目全部选中的时候对应的父条目也要设置选中状态
    3.当父条目选中的时候全选按钮也是选中状态
    4.当全选的时候父条目就为选中状态,但是还要关联子控件也要一块选中
    5.不管每次点击父条目还是子条目的CheckBox都要做改变数据的操作,所以需要刷新适配器
    6.点击CheckBox为选中状态的时候需要将总价和总数量计算出来
    7.赋值肯定是一个刷新UI的操作,需要每次点击都要重新赋值

简单的购物车的效果如下图:
在这里插入图片描述
虽然这个效果有点丑,但是里边还是有些逻辑性的代码
这里有一些MVP和抽取基类的一些东西
如果没看懂的话具体放到GitHup上来展示
项目地址:https://github.com/qq1341738311/ShopingDemo

下面展示一下代码
MainActivity

public class MainActivity extends BaseActivity implements IView, View.OnClickListener{
    private IPresenterImpl iPresenter;
    private ExpandableListView mExpandableList;
    private String mUrl = "http://www.wanandroid.com/tools/mockapi/6523/restaurant-list";
    private MyAdapter adapter;
    private CheckBox mAllCheck;
    private TextView mAllContent;
    private TextView mAllPrice;
    private boolean boo;

    @Override
    protected int getLayout() {
        return R.layout.activity_main;
    }

    @Override
    protected void initViews() {
        mExpandableList = findViewById(R.id.main_expandale_list);
        mAllCheck = findViewById(R.id.main_check_allCheck);
        mAllContent = findViewById(R.id.main_text_allContent);
        mAllPrice = findViewById(R.id.main_text_allPrice);
    }

    @Override
    protected void onClicks() {
        mAllCheck.setOnClickListener(this);
    }

    @Override
    protected void progress() {
        iPresenter = new IPresenterImpl(this);
        iPresenter.getString(mUrl);
    }

    @Override
    public void getData(Object data) {
        GroupAndChildBean bean = (GroupAndChildBean) data;
        List<GroupAndChildBean.DataBean> list = bean.getData();
        adapter = new MyAdapter(list, MainActivity.this);
        mExpandableList.setAdapter(adapter);
        //接口回调得到总价格和总数量(这里我设置的是每次点击的时候都会传一次值,便于我们更新UI)
        adapter.setInter(new Inter_getData() {
            @Override
            public void getData(Object data) {
                boolean da = (boolean) data;
                if(da==true){
                    mAllCheck.setChecked(true);
                }else{
                    mAllCheck.setChecked(false);
                }
            }

            @Override
            public void getNumPrice(Object price) {
                mAllPrice.setText("总价格:"+price);
            }

            @Override
            public void getNumContent(Object content) {
                mAllContent.setText("总数量:"+content);
            }
        });
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()){
            case R.id.main_check_allCheck:
                if(mAllCheck.isChecked()){
                    boo = true;
                    //当点击全选的时候联动父控件和子控件
                    adapter.setAll(boo);
                    //当全选的时候就是判断全部的价格和全部的数量
                    float adapterPrice = adapter.getPrice();
                    int adapterContent = adapter.getContent();
                    mAllContent.setText("总数量:"+adapterContent);
                    mAllPrice.setText("总价格:"+adapterPrice);
                }else{
                    boo = false;
                    //默认赋值
                    mAllContent.setText("总数量:"+0);
                    mAllPrice.setText("总价格:"+0);
                    //当点击全选的时候联动父控件和子控件
                    adapter.setAll(boo);
                }
                break;
        }
    }

}

适配器

public class MyAdapter extends BaseExpandableListAdapter {
    private List<GroupAndChildBean.DataBean> mList;
    private Context mContent;
    private Inter_getData inter_getData;

    //定义有参构造,需要我们从MainActivity传数据
    public MyAdapter(List<GroupAndChildBean.DataBean> mList, Context mContent) {
        this.mList = mList;
        this.mContent = mContent;
    }
    //定义接口
    public void setInter(Inter_getData inter_getData){
        this.inter_getData = inter_getData;
    }
    //父级的Holder
    class MyGroupHplder{
        public CheckBox group_checkBox;
        public TextView group_name;
    };
    //子级的Holder
    class MyChildHplder{
        public CheckBox child_checkBox;
        public ImageView child_img;
        public TextView child_name,child_price;
        public zdy_NumContent child_content;
    };

    //父控件的条目数量
    @Override
    public int getGroupCount() {
        return mList.size();
    }
    //子控件的条目数量
    @Override
    public int getChildrenCount(int i) {
        return mList.get(i).getSpus().size();
    }

    @Override
    public Object getGroup(int i) {
        return null;
    }

    @Override
    public Object getChild(int i, int i1) {
        return null;
    }

    @Override
    public long getGroupId(int i) {
        return 0;
    }

    @Override
    public long getChildId(int i, int i1) {
        return 0;
    }

    @Override
    public boolean hasStableIds() {
        return false;
    }

    @Override
    public boolean isChildSelectable(int i, int i1) {
        return false;
    }

    //父控件优化、赋值、和相应操作
    @Override
    public View getGroupView(final int i, boolean b, View view, ViewGroup viewGroup) {
        MyGroupHplder myGroupHplder;
        if(view==null){
            myGroupHplder = new MyGroupHplder();
            view = View.inflate(mContent, R.layout.item_group, null);
            myGroupHplder.group_checkBox = view.findViewById(R.id.item_group_check);
            myGroupHplder.group_name = view.findViewById(R.id.item_group_name);
            view.setTag(myGroupHplder);
        }else{
            myGroupHplder = (MyGroupHplder) view.getTag();
        }
        //-----------------------------------------------------------------------------------------------------------------------------------------------------------------
        //因为我们在每次点击checkBox的时候才会改变状态,判断我们的方法里的条件是否成立
        myGroupHplder.group_checkBox.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                setOnClickGroup(i);
                //接口回调(将是否全选、总价格、总数量的值通过接口回调传入我们的MainActivity)
                boolean onAll = OnAll();
                float price = getPrice();
                int content = getContent();
                if(inter_getData!=null){
                    inter_getData.getData(onAll);
                    inter_getData.getNumPrice(price);
                    inter_getData.getNumContent(content);
                }
                //点击完之后肯定会将值改变所以需要我们每次点击的时候做刷新适配器的操作
                notifyDataSetChanged();
            }
        });
        //赋值
        myGroupHplder.group_checkBox.setChecked(mList.get(i).getGroup_checked());
        myGroupHplder.group_name.setText(mList.get(i).getName());
        return view;
    }
    //子控件优化、赋值、和相应操作
    @Override
    public View getChildView(final int i,final int i1, boolean b, View view, ViewGroup viewGroup) {
        MyChildHplder myChildHplder;
        if(view==null){
            myChildHplder = new MyChildHplder();
            view = View.inflate(mContent, R.layout.item_child, null);
            myChildHplder.child_checkBox = view.findViewById(R.id.item_child_check);
            myChildHplder.child_img = view.findViewById(R.id.item_child_img);
            myChildHplder.child_name = view.findViewById(R.id.item_child_name);
            myChildHplder.child_price = view.findViewById(R.id.item_child_price);
            myChildHplder.child_content = view.findViewById(R.id.item_child_content);
            view.setTag(myChildHplder);
        }else{
            myChildHplder = (MyChildHplder) view.getTag();
        }
        final List<GroupAndChildBean.DataBean.SpusBean> list = mList.get(i).getSpus();
        //-----------------------------------------------------------------------------------------------------------------------------------------------------------------
        myChildHplder.child_checkBox.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //点击子控件设置选中和未选中状态
                setOnClickChild(i, i1);
                //这个方法是判断当子控件全部选中的时候给父控件也选中
                setAllChild(i);
                //下面将数据传入MainActivity
                float price = getPrice();
                int content = getContent();
                if(inter_getData!=null){
                    inter_getData.getNumPrice(price);
                    inter_getData.getNumContent(content);
                }
                notifyDataSetChanged();
            }
        });

        myChildHplder.child_checkBox.setChecked(list.get(i1).getChild_checked());
        Picasso.get().load(list.get(i1).getPic_url()).into(myChildHplder.child_img);
        myChildHplder.child_name.setText(list.get(i1).getName());
        myChildHplder.child_price.setText(list.get(i1).getSkus().get(0).getPrice());
//        myChildHplder.child_content.setText(list.get(i1).getPraise_num()+"");
        myChildHplder.child_content.setAllNum(list.get(i1).getPraise_num()+"");

        //这里我用的是自定义View实现后边的数量加的操作
        myChildHplder.child_content.setJiaOnclick(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                int praise_num = list.get(i1).getPraise_num();
                praise_num++;
                list.get(i1).setPraise_num(praise_num);
                notifyDataSetChanged();
                float price = getPrice();
                int content = getContent();
                if(inter_getData!=null){
                    inter_getData.getNumPrice(price);
                    inter_getData.getNumContent(content);
                }
            }
        });
        //这里我用的是自定义View实现后边的数量减的操作
        myChildHplder.child_content.setJianOnClick(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                int praise_num = list.get(i1).getPraise_num();
                if(praise_num>0){
                    praise_num--;
                    list.get(i1).setPraise_num(praise_num);
                }else{
                    Toast.makeText(mContent,"已经是最小数量了",Toast.LENGTH_SHORT).show();
                    praise_num = 0;
                    list.get(i1).setPraise_num(praise_num);
                }
                notifyDataSetChanged();
                float price = getPrice();
                int content = getContent();
                if(inter_getData!=null){
                    inter_getData.getNumPrice(price);
                    inter_getData.getNumContent(content);
                }
            }
        });
        return view;
    }

    //父控件将父控件内的子控件全部选中
    public void setOnClickGroup(int position){
        if(mList.get(position).getGroup_checked()){
            mList.get(position).setGroup_checked(false);
            for (int i = 0; i < mList.get(position).getSpus().size(); i++) {
                mList.get(position).getSpus().get(i).setChild_checked(false);
            }
        }else{
            mList.get(position).setGroup_checked(true);
            for (int i = 0; i < mList.get(position).getSpus().size(); i++) {
                mList.get(position).getSpus().get(i).setChild_checked(true);
            }
        }
    }

    //子控件选中
    public void setOnClickChild(int groupPosition,int childPosition){
        GroupAndChildBean.DataBean.SpusBean bean = mList.get(groupPosition).getSpus().get(childPosition);
        if(bean.getChild_checked()){
            bean.setChild_checked(false);
        }else{
            bean.setChild_checked(true);
        }
    }

    //当子控件全部选中的时候给父控件也选中
    public void setAllChild(int groupPosition){
        boolean boo = true;
        for (int i = 0; i < mList.get(groupPosition).getSpus().size(); i++) {
            GroupAndChildBean.DataBean.SpusBean bean = mList.get(groupPosition).getSpus().get(i);
            if(!bean.getChild_checked()){
                boo=false;
            }
        }
        if(boo==true){
            mList.get(groupPosition).setGroup_checked(true);
            boolean onAll = OnAll();
            if(inter_getData!=null){
                inter_getData.getData(onAll);
            }
        }else{
            mList.get(groupPosition).setGroup_checked(false);
            boolean onAll = OnAll();
            if(inter_getData!=null){
                inter_getData.getData(onAll);
            }
        }
    }

    //当父控件全部选中的时候把全选按钮设置为选中状态
    public void setAll(boolean allCheck){
        if(allCheck==true){
            for (int i = 0; i < mList.size(); i++) {
                mList.get(i).setGroup_checked(!allCheck);
                notifyDataSetChanged();
                setOnClickGroup(i);
            }
        }else{
            for (int i = 0; i < mList.size(); i++) {
                mList.get(i).setGroup_checked(!allCheck);
                notifyDataSetChanged();
                setOnClickGroup(i);
            }
        }
    }

    当父控件全部选中的时候把全选按钮设置为选中状态
    public boolean OnAll(){
        boolean boo = true;
        for (int i = 0; i < mList.size(); i++) {
            if(!mList.get(i).getGroup_checked()){
                boo = false;
            }
        }
        return boo;
    }

    //获取总价格
    public float getPrice(){
        float zPrice = 0;
        for (int i = 0; i < mList.size(); i++) {
            List<GroupAndChildBean.DataBean.SpusBean> list = mList.get(i).getSpus();
            for (int j = 0; j < list.size(); j++) {
                if(list.get(j).getChild_checked()){
                    float price = Float.parseFloat(list.get(j).getSkus().get(0).getPrice());
                    int content = list.get(j).getPraise_num();
                    zPrice += content*price;
                }
            }
        }
        return zPrice;
    }

    //获取总数量
    public int getContent(){
        int zContent = 0;
        for (int i = 0; i < mList.size(); i++) {
            List<GroupAndChildBean.DataBean.SpusBean> list = mList.get(i).getSpus();
            for (int j = 0; j < list.size(); j++) {
                if(list.get(j).getChild_checked()){
                    int content = list.get(j).getPraise_num();
                    zContent += content;
                }
            }
        }
        return zContent;
    }

}

接口回调

public interface Inter_getData<T> {
    void getData(T data);
    void getNumPrice(T price);
    void getNumContent(T content);
}

自定义View组合控件实现加减的地方

public class zdy_NumContent extends LinearLayout{

    private ImageView mImgJia;
    private ImageView mImgJian;
    private TextView mAllContent;

    public zdy_NumContent(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);

        LayoutInflater.from(context).inflate(R.layout.zdy_layout,this);
        mImgJia = findViewById(R.id.layout_img_jia);
        mImgJian = findViewById(R.id.layout_img_jian);
        mAllContent = findViewById(R.id.layout_All_Content);
    }

    public void setJiaOnclick(OnClickListener onclick){
        mImgJia.setOnClickListener(onclick);
    }

    public void setJianOnClick(OnClickListener onClick){
        mImgJian.setOnClickListener(onClick);
    }

    public void setAllNum(String num){
        mAllContent.setText(num);
    }
}

自定义View引用的布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:orientation="horizontal"
    android:layout_height="match_parent">

    <ImageView
        android:id="@+id/layout_img_jia"
        android:layout_width="40dp"
        android:src="@drawable/jia"
        android:layout_gravity="center_vertical"
        android:layout_height="40dp" />

    <TextView
        android:id="@+id/layout_All_Content"
        android:gravity="center_vertical"
        android:layout_width="wrap_content"
        android:layout_height="40dp" />

    <ImageView
        android:id="@+id/layout_img_jian"
        android:src="@drawable/jian"
        android:layout_width="40dp"
        android:layout_gravity="center_vertical"
        android:layout_height="40dp" />

</LinearLayout>

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <ExpandableListView
        android:layout_above="@+id/asd"
        android:id="@+id/main_expandale_list"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>


    <LinearLayout
        android:id="@+id/asd"
        android:layout_alignParentBottom="true"
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <CheckBox
            android:id="@+id/main_check_allCheck"
            android:layout_weight="1"
            android:text="全选"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />

        <TextView
            android:id="@+id/main_text_allContent"
            android:text="总数量:0"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />

        <TextView
            android:id="@+id/main_text_allPrice"
            android:layout_weight="1"
            android:text="总价格:0"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
    </LinearLayout>


</RelativeLayout>

item_group.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:orientation="horizontal"
    android:layout_height="match_parent">

    <!--这里有一点这里面这哥CheckBox会抢焦点,导致无法点击条目-->
    <!--解决方法加这个属性android:focusable="false"-->
    <CheckBox
        android:id="@+id/item_group_check"
        android:focusable="false"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <TextView
        android:id="@+id/item_group_name"
        android:textSize="30dp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

</LinearLayout>

item_child.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:orientation="horizontal"
    android:layout_height="match_parent">

    <CheckBox
        android:id="@+id/item_child_check"
        android:layout_width="wrap_content"
        android:layout_gravity="center_vertical"
        android:layout_height="wrap_content" />

    <ImageView
        android:id="@+id/item_child_img"
        android:layout_width="100dp"
        android:layout_height="100dp" />

    <LinearLayout
        android:orientation="vertical"
        android:layout_weight="1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <TextView
            android:id="@+id/item_child_name"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />

        <TextView
            android:id="@+id/item_child_price"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />
    </LinearLayout>

    <demo.bwie.com.shopping_trolley_demo.zdy_NumContent
        android:id="@+id/item_child_content"
        android:layout_gravity="center_vertical"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</LinearLayout>
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值