购物车---二级列表---详细注释

activity_main

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
    android:orientation="vertical"
    tools:context=".MainActivity">
    <ExpandableListView
        android:id="@+id/ex_listView"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="10" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:orientation="horizontal">

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

        <TextView
            android:id="@+id/all_price"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="总价:¥0.00"
            android:textSize="18sp" />

        <Button
            android:id="@+id/jiesuan_btn"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="结算" />
    </LinearLayout>

</LinearLayout>

加减器 add_sub_item

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

    <TextView
        android:id="@+id/sub_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:text="-"
        android:textSize="20sp" />

    <TextView
        android:id="@+id/num_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:text="1"
        android:textSize="20sp" />

    <TextView
        android:id="@+id/add_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:text="+"
        android:textSize="20sp" />
</LinearLayout>

组布局 parent_item

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

    <CheckBox
        android:id="@+id/box_parent"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"/>

    <TextView
        android:id="@+id/text_parent"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="商家"
        android:textSize="20sp"
        android:layout_gravity="center"/>
</LinearLayout>

子布局 child_item

<?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="120dp">

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

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

        <ImageView
            android:id="@+id/child_image"
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:padding="10dp"
            android:src="@mipmap/ic_launcher" />


    </LinearLayout>

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

        <TextView
            android:id="@+id/child_text"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:paddingTop="15dp"
            android:text="jhsjhdsk"
            android:textSize="17sp" />

        <TextView
            android:id="@+id/child_price"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:paddingTop="10dp"
            android:text="¥0.0" />


    </LinearLayout>

    <wanghuiqi.bawie.com.whq_shop.view.MyAddSub
        android:id="@+id/add_sub"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:gravity="center_vertical" />
</LinearLayout>

加减器 MyAddSub

package wanghuiqi.bawie.com.whq_shop.view;

import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.widget.ExpandableListView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;

import wanghuiqi.bawie.com.whq_shop.R;

public class MyAddSub extends LinearLayout implements View.OnClickListener {

    private TextView addText;
    private TextView subText;
    private TextView numText;
    private int number = 1;

    public MyAddSub(Context context) {
        this(context, null);
    }

    public MyAddSub(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public MyAddSub(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        View view = inflate(context, R.layout.add_sub_item, this);
        addText = view.findViewById(R.id.add_text);
        subText = view.findViewById(R.id.sub_text);
        numText = view.findViewById(R.id.num_text);

        addText.setOnClickListener(this);
        subText.setOnClickListener(this);

    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.add_text:
                ++number;
                numText.setText(number + "");
                if (mOnNumberChangeInterface != null) {
                    mOnNumberChangeInterface.onNumberChang(number);
                }
                break;
            case R.id.sub_text:
                //判断如果数字比1大就减,比1小就吐司
                if (number > 1) {
                    --number;
                    numText.setText(number + "");
                    if (mOnNumberChangeInterface != null) {
                        mOnNumberChangeInterface.onNumberChang(number);
                    }
                } else {
                    Toast.makeText(getContext(), "不能再少了", Toast.LENGTH_SHORT).show();
                }
                break;
        }
    }

    public int getNumber() {
        return number;
    }

    public void setNumber(int number) {
        this.number = number;
        numText.setText(number + "");
    }

    //创建接口
    public interface OnNumberChangeInterface {
        void onNumberChang(int num);
    }

    //声明接口名
    private OnNumberChangeInterface mOnNumberChangeInterface;

    //暴露方法
    public void setOnNumberChangeInterface(OnNumberChangeInterface onNumberChangeInterface) {
        mOnNumberChangeInterface = onNumberChangeInterface;
    }
}

adapter ShopAdapter

package wanghuiqi.bawie.com.whq_shop.adapter;

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 com.squareup.picasso.Picasso;

import java.util.List;

import wanghuiqi.bawie.com.whq_shop.R;
import wanghuiqi.bawie.com.whq_shop.model.bean.Shop;
import wanghuiqi.bawie.com.whq_shop.view.MyAddSub;

public class ShopAdapter extends BaseExpandableListAdapter {
    private List<Shop.DataBean> shopData;

    public ShopAdapter(List<Shop.DataBean> shopData) {
        this.shopData = shopData;
    }

    //1.有多少按钮
    @Override
    public int getGroupCount() {
        return shopData.size();
    }

    //2.一个组里有多少子条目
    @Override
    public int getChildrenCount(int groupPosition) {
        return shopData.get(groupPosition).getList().size();
    }


    ////////P.组布局////////
    @Override
    public View getGroupView(final int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
        //P1.获取组的下标
        Shop.DataBean dataBean = shopData.get(groupPosition);
        ParentHolder parentHolder;
        if (convertView == null) {
            convertView = View.inflate(parent.getContext(), R.layout.parent_item, null);
            parentHolder = new ParentHolder(convertView);
            convertView.setTag(parentHolder);
        } else {
            parentHolder = (ParentHolder) convertView.getTag();
        }
        //P2.获取商家名称
        parentHolder.textParent.setText(dataBean.getSellerName());
        //P3.根据当前商家的所有商品,确定checkbox是否选中
        boolean parentAllSelect = isParentAllSelect(groupPosition);
        //P4.1根据boolean判断是否选中
        parentHolder.boxParent.setChecked(parentAllSelect);
        //P5.设置点击checkbox的点击事件,接口回调
        parentHolder.boxParent.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (mOnCartListChangeListener != null) {
                    mOnCartListChangeListener.onParentCheckedChange(groupPosition);
                }
            }
        });
        return convertView;
    }


    ////////////C.子布局///////////
    @Override
    public View getChildView(final int groupPosition, final int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
        Shop.DataBean dataBean = shopData.get(groupPosition);
        List<Shop.DataBean.ListBean> list = dataBean.getList();
        //C1.拿到list集合里具体商品
        Shop.DataBean.ListBean listBean = list.get(childPosition);
        ChildHolder childHolder;
        if (convertView == null) {
            convertView = View.inflate(parent.getContext(), R.layout.child_item, null);
            childHolder = new ChildHolder(convertView);
            convertView.setTag(childHolder);
        } else {
            childHolder = (ChildHolder) convertView.getTag();
        }
        //C2.截取图片picasso
        String images = listBean.getImages();
        String[] strings = images.split("!");
        Picasso.with(parent.getContext()).load(strings[0]).into(childHolder.imageChild);
        //C.获取商品名称
        childHolder.childText.setText(listBean.getTitle());
        //C.单价
        childHolder.childPrice.setText(listBean.getPrice() + "");
        //C.设置子条目复选框是否选中
        childHolder.boxChild.setChecked(listBean.getSelected() == 1);
        //C.设置加减器内部数量
        childHolder.addSub.setNumber(listBean.getNum());

        //C3.设置商品checkbox的点击事件,接口回调
        childHolder.boxChild.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (mOnCartListChangeListener != null) {
                    mOnCartListChangeListener.onChildCheckedChange(groupPosition, childPosition);
                }
            }
        });

        //C4.设置加减器的点击事件,接口回调
        childHolder.addSub.setOnNumberChangeInterface(new MyAddSub.OnNumberChangeInterface() {
            @Override
            public void onNumberChang(int num) {
                if (mOnCartListChangeListener != null) {
                    mOnCartListChangeListener.onAddSubNumberChange(groupPosition, childPosition, num);
                }
            }
        });

        return convertView;
    }

    //--------判断当前商品是否被选中--------
    public boolean isParentAllSelect(int groupPosition) {
        //拿到组的数据
        Shop.DataBean dataBean = shopData.get(groupPosition);
        //拿到商家所有商品,集合
        List<Shop.DataBean.ListBean> list = dataBean.getList();
        for (int i = 0; i < list.size(); i++) {
            //判断这个组所有商品是否被选中,如有一个未选中就都不选中
            if (list.get(i).getSelected() == 0) {
                return false;
            }
        }
        return true;
    }

    //------底部全选按钮逻辑判断------
    public boolean isAllSelected() {
        for (int i = 0; i < shopData.size(); i++) {
            Shop.DataBean dataBean = shopData.get(i);
            List<Shop.DataBean.ListBean> list = dataBean.getList();
            for (int j = 0; j < list.size(); j++) {
                //判断组的商品是否被选中
                if (list.get(j).getSelected() == 0) {
                    return false;
                }
            }
        }
        return true;
    }

    //-----计算商品总数量-----
    public int TotalNumber() {
        int totalNumber = 0;
        for (int i = 0; i < shopData.size(); i++) {
            Shop.DataBean dataBean = shopData.get(i);
            List<Shop.DataBean.ListBean> list = dataBean.getList();
            for (int j = 0; j < list.size(); j++) {
                //商品数量,选中的
                if (list.get(j).getSelected() == 1) {
                    //拿到商品的数量
                    int num = list.get(j).getNum();
                    totalNumber += num;
                }
            }
        }
        return totalNumber;
    }

    //-------计算商品总价格-------
    public float TotalPrice() {
        float totalPrice = 0;
        for (int i = 0; i < shopData.size(); i++) {
            Shop.DataBean dataBean = shopData.get(i);
            List<Shop.DataBean.ListBean> list = dataBean.getList();
            for (int j = 0; j < list.size(); j++) {
                //商品价格,选中的
                if (list.get(j).getSelected() == 1) {
                    //拿到商品数量
                    double price = list.get(j).getPrice();
                    int num = list.get(j).getNum();
                    totalPrice += price + num;
                }
            }
        }
        return totalPrice;
    }

    //--------根据选择,更改选框里状态------
    public void changeSellerAllProduct(int groupPosition, boolean isSelected) {
        Shop.DataBean dataBean = shopData.get(groupPosition);
        List<Shop.DataBean.ListBean> list = dataBean.getList();
        for (int i = 0; i < list.size(); i++) {
            Shop.DataBean.ListBean listBean = list.get(i);
            listBean.setSelected(isSelected ? 1 : 0);
        }
    }

    //---------当子条目选中,更新组选框的状态-------
    public void changeChild(int groupPosition, int childPosition) {
        Shop.DataBean dataBean = shopData.get(groupPosition);
        List<Shop.DataBean.ListBean> list = dataBean.getList();
        Shop.DataBean.ListBean listBean = list.get(childPosition);
        listBean.setSelected(listBean.getSelected() == 0 ? 1 : 0);
    }

    //---------当最底部全选框选中,更新所有选框的状态
    public void changAllCheckBox(boolean selected) {
        for (int i = 0; i < shopData.size(); i++) {
            Shop.DataBean dataBean = shopData.get(i);
            List<Shop.DataBean.ListBean> list = dataBean.getList();
            for (int j = 0; j < list.size(); j++) {
                list.get(j).setSelected(selected ? 1 : 0);
            }
        }
    }
    //----------当加减器被点击时,改变商品数量--------
    public void changProductNumber(int groupPosition, int childPosition, int number){
        Shop.DataBean dataBean = shopData.get(groupPosition);
        List<Shop.DataBean.ListBean> list = dataBean.getList();
        Shop.DataBean.ListBean listBean = list.get(childPosition);
        listBean.setNum(number);
    }

    //==============Viewhodler============
    //组的Viewholder
    public static class ParentHolder {

        private final CheckBox boxParent;
        private final TextView textParent;

        public ParentHolder(View rootView) {
            boxParent = rootView.findViewById(R.id.box_parent);
            textParent = rootView.findViewById(R.id.text_parent);
        }
    }

    public static class ChildHolder {

        private final CheckBox boxChild;
        private final ImageView imageChild;
        private final TextView childText;
        private final TextView childPrice;
        private final MyAddSub addSub;

        public ChildHolder(View rootView) {
            boxChild = rootView.findViewById(R.id.child_box);
            imageChild = rootView.findViewById(R.id.child_image);
            childText = rootView.findViewById(R.id.child_text);
            childPrice = rootView.findViewById(R.id.child_price);
            addSub = rootView.findViewById(R.id.add_sub);
        }
    }

    //=============创建接口===========
    public interface onCartListChangeListener {
        /*当组的checkbox点击时回调*/
        void onParentCheckedChange(int groupPosition);

        /*当点击子条目商品的checkbox回调*/
        void onChildCheckedChange(int groupPosition, int childPosition);

        /*当点击加减按钮的回调*/
        void onAddSubNumberChange(int groupPosition, int childPosition, int number);
    }

    private onCartListChangeListener mOnCartListChangeListener;

    public void setOnCartListChangeListener(onCartListChangeListener onCartListChangeListener) {
        mOnCartListChangeListener = onCartListChangeListener;
    }

    //不管这些
    @Override
    public boolean isChildSelectable(int groupPosition, int childPosition) {
        return false;
    }

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

    @Override
    public Object getChild(int groupPosition, int childPosition) {
        return null;
    }

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

    @Override
    public long getChildId(int groupPosition, int childPosition) {
        return 0;
    }

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

工具类 HttpUtils

package wanghuiqi.bawie.com.whq_shop.model;

import android.os.Handler;
import android.os.Looper;

import java.io.IOException;
import java.util.concurrent.TimeUnit;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;

public class HttpUtils {

    private final Handler handler;
    private final OkHttpClient httpClient;
    private static HttpUtils mHttpUtils;

    private HttpUtils(){
        //创建主线程的handler
        handler = new Handler(Looper.getMainLooper());
        httpClient = new OkHttpClient.Builder()
                .connectTimeout(500, TimeUnit.MILLISECONDS)
                .readTimeout(5000, TimeUnit.MILLISECONDS)
                .writeTimeout(5000, TimeUnit.MILLISECONDS)
                .build();
    }
    //创建接口
    public interface OKhttpInterface{
        void Failed(Exception e);
        void Success(String data);
    }
    public void doGet(String url, final OKhttpInterface mOkhttpInterface){
        Request request = new Request.Builder()
                .get()
                .url(url)
                .build();
        httpClient.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, final IOException e) {
                if (mOkhttpInterface!=null){
                    //切换到主线程
                    handler.post(new Runnable() {
                        @Override
                        public void run() {
                            mOkhttpInterface.Failed(e);
                        }
                    });
                }
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                if (response!=null&&response.isSuccessful()){
                    final String data = response.body().string();
                    handler.post(new Runnable() {
                        @Override
                        public void run() {
                            if (mOkhttpInterface!=null){
                                mOkhttpInterface.Success(data);
                                return;
                            }
                        }
                    });
                }
            }
        });
    }
    //单例模式
    public static HttpUtils getInstance(){
        if (mHttpUtils==null){
            synchronized (HttpUtils.class){
                if (mHttpUtils==null){
                    return mHttpUtils=new HttpUtils();
                }
            }
        }
        return mHttpUtils;
    }
}

ShopPresenter P层

package wanghuiqi.bawie.com.whq_shop.presenter;
import com.google.gson.Gson;
import java.util.List;
import wanghuiqi.bawie.com.whq_shop.model.HttpUtils;
import wanghuiqi.bawie.com.whq_shop.model.bean.Shop;

public class ShopPresenter {
    public void ShopData(String url) {
        HttpUtils.getInstance().doGet(url, new HttpUtils.OKhttpInterface() {
            @Override
            public void Failed(Exception e) {
                mOnshopInterface.failed(e);
            }

            @Override
            public void Success(String data) {
                Shop shop = new Gson().fromJson(data, Shop.class);
                List<Shop.DataBean> shopData = shop.getData();
                mOnshopInterface.success(shopData);
            }
        });
    }

    public interface onShopInterface {
        void failed(Exception e);

        void success(List<Shop.DataBean> shopData);
    }

    private onShopInterface mOnshopInterface;

    public void setOnshopInterface(onShopInterface onshopInterface) {
        mOnshopInterface = onshopInterface;
    }
}

MainActivity

package wanghuiqi.bawie.com.whq_shop;

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 java.util.List;

import wanghuiqi.bawie.com.whq_shop.adapter.ShopAdapter;
import wanghuiqi.bawie.com.whq_shop.model.bean.Shop;
import wanghuiqi.bawie.com.whq_shop.presenter.ShopPresenter;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private ExpandableListView ex_listView;
    private CheckBox all_box;
    private TextView all_price;
    private Button jiesuan_btn;
    private ShopAdapter shopAdapter;
    private String url = "http://www.zhaoapi.cn/product/getCarts?uid=71";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //A.获取控件
        initView();
        //B.获取数据
        initData();
    }

    //B.获取数据
    private void initData() {
        ShopPresenter shopPresenter = new ShopPresenter();
        shopPresenter.ShopData(url);
        shopPresenter.setOnshopInterface(new ShopPresenter.onShopInterface() {

            @Override
            public void failed(Exception e) {

            }

            @Override
            public void success(List<Shop.DataBean> shopData) {
                //B1.获取适配器
                shopAdapter = new ShopAdapter(shopData);
                //B2.对适配器设置监听(加减器,组,子条目复选框改变)
                shopAdapter.setOnCartListChangeListener(new ShopAdapter.onCartListChangeListener() {
                    //------B2.1.组的复选框被点击------
                    @Override
                    public void onParentCheckedChange(int groupPosition) {
                        boolean parentAllSelect = shopAdapter.isParentAllSelect(groupPosition);
                        shopAdapter.changeSellerAllProduct(groupPosition, !parentAllSelect);
                        shopAdapter.notifyDataSetChanged();
                        //刷新底部
                        refreshAllShop();

                    }

                    //-------B2.2.子条目的复选框被点击-------
                    @Override
                    public void onChildCheckedChange(int groupPosition, int childPosition) {
                        shopAdapter.changeChild(groupPosition, childPosition);
                        shopAdapter.notifyDataSetChanged();
                        refreshAllShop();
                    }

                    //-------B2.3.加减器被点击------
                    @Override
                    public void onAddSubNumberChange(int groupPosition, int childPosition, int number) {
                        shopAdapter.changProductNumber(groupPosition, childPosition, number);
                        shopAdapter.notifyDataSetChanged();
                        refreshAllShop();
                    }
                });
                //B3.设置adapter对象
                ex_listView.setAdapter(shopAdapter);
                //B4.展开二级列表
                for (int i=0;i<shopData.size();i++){
                    ex_listView.expandGroup(i);
                }
            }
        });
    }


    //-------底部全选框的点击事件--------
    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.all_box:
                boolean allSelected = shopAdapter.isAllSelected();
                shopAdapter.changAllCheckBox(!allSelected);
                shopAdapter.notifyDataSetChanged();
                //刷新底部的数据显示
                refreshAllShop();
                break;
        }
    }

    //--------刷新底部---------
    private void refreshAllShop() {
        //判断是否所有商品都被选中
        boolean allSelected = shopAdapter.isAllSelected();
        //设置给checkbox
        all_box.setChecked(allSelected);
        //计算总计
        float price = shopAdapter.TotalPrice();
        all_price.setText("总计" + price);
        //计算数量
        int number = shopAdapter.TotalNumber();
        jiesuan_btn.setText("去结算(" + number + ")");

    }


    //A.初始化控件
    private void initView() {
        ex_listView = findViewById(R.id.ex_listView);
        all_box = findViewById(R.id.all_box);
        all_price = findViewById(R.id.all_price);
        jiesuan_btn = findViewById(R.id.jiesuan_btn);

        all_box.setOnClickListener(this);
    }
}

猜你喜欢

转载自blog.csdn.net/WhuiQi/article/details/84348694