Android實現商城購物車功能

longxuanzhigu發表於2019-06-19

最近公司專案做商城模組,需要實現購物車功能,主要實現了單選、全選,金額合計,商品刪除,商品數量加減等功能,先看看效果圖:

在這裡插入圖片描述
一、實現步驟: 0、新增依賴庫 1.購物車主介面佈局檔案(activity_main.xml) 2.購物車實現邏輯主介面(MainActivity.class) 3.使用ExpandableListView,繼承BaseExpandableListAdapter 4.購物車資料的bean類(ShoppingCarDataBean.class) 5.分店鋪實現佈局 6.購物車中商品Item佈局檔案

二、實現過程:

0.新增依賴庫

    implementation 'com.jakewharton:butterknife:5.1.1'
    implementation 'com.google.code.gson:gson:2.2.4'
    implementation 'com.github.bumptech.glide:glide:3.7.0'
複製程式碼

1.購物車主介面佈局檔案(activity_main.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="match_parent"
    android:background="#ffffff"
    android:orientation="vertical">

    <LinearLayout
        android:id="@+id/ll_gouwuche"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#ededed"
        android:orientation="vertical">

        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="48dp"
            android:background="#ffffff"
            android:orientation="vertical">


            <ImageView
                android:id="@+id/tv_titlebar_left"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerVertical="true"
                android:layout_marginLeft="15dp"
                android:padding="5dp"
                android:src="@drawable/danghanglan_fanhui" />

            <TextView
                android:id="@+id/tv_titlebar_center"
                android:layout_width="200dp"
                android:layout_height="match_parent"
                android:layout_centerHorizontal="true"
                android:ellipsize="end"
                android:gravity="center"
                android:maxLength="18"
                android:singleLine="true"
                android:text="購物車"
                android:textColor="#2f302b"
                android:textSize="17sp"
                android:visibility="visible" />

            <TextView
                android:id="@+id/tv_titlebar_right"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:layout_alignParentRight="true"
                android:background="@null"
                android:gravity="center"
                android:paddingLeft="15dp"
                android:paddingRight="15dp"
                android:singleLine="true"
                android:text="編輯"
                android:textColor="#2f302b"
                android:textSize="14sp"
                android:visibility="gone" />

            <View
                android:layout_width="match_parent"
                android:layout_height="0.5dp"
                android:layout_alignParentBottom="true"
                android:background="#cccccc" />
        </RelativeLayout>

        <ExpandableListView
            android:id="@+id/elv_shopping_car"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:background="#ededed"
            android:divider="@null"
            android:groupIndicator="@null"
            android:scrollbars="none"
            android:visibility="gone" />

        <RelativeLayout
            android:id="@+id/rl"
            android:layout_width="match_parent"
            android:layout_height="54dp"
            android:background="#ffffff"
            android:visibility="gone">

            <LinearLayout
                android:id="@+id/ll_select_all"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:orientation="horizontal"
                android:paddingRight="10dp">

                <ImageView
                    android:id="@+id/iv_select_all"
                    android:layout_width="20dp"
                    android:layout_height="20dp"
                    android:layout_gravity="center_vertical"
                    android:layout_marginLeft="10dp"
                    android:background="@drawable/gouwuche_unselect_bg" />

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center"
                    android:layout_marginLeft="6dp"
                    android:text="全選"
                    android:textColor="#666666"
                    android:textSize="12dp" />
            </LinearLayout>

            <Button
                android:id="@+id/btn_order"
                android:layout_width="125dp"
                android:layout_height="40dp"
                android:layout_alignParentRight="true"
                android:layout_centerVertical="true"
                android:layout_marginRight="15dp"
                android:background="@drawable/jiarugouwuche_bg"
                android:text="結算"
                android:textColor="#ffffff"
                android:textSize="16dp"
                android:visibility="visible" />

            <Button
                android:id="@+id/btn_delete"
                android:layout_width="125dp"
                android:layout_height="40dp"
                android:layout_alignParentRight="true"
                android:layout_centerVertical="true"
                android:layout_marginRight="15dp"
                android:background="@drawable/jiarugouwuche_bg"
                android:text="刪除"
                android:textColor="#ffffff"
                android:textSize="16dp"
                android:visibility="gone" />

            <RelativeLayout
                android:id="@+id/rl_total_price"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:layout_toLeftOf="@id/btn_order"
                android:layout_toRightOf="@id/ll_select_all">

                <TextView
                    android:id="@+id/tv_total_price"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_alignParentRight="true"
                    android:layout_centerVertical="true"
                    android:layout_marginLeft="2dp"
                    android:layout_marginRight="10dp"
                    android:maxLength="12"
                    android:singleLine="true"
                    android:text="¥0.00"
                    android:textColor="#d8b691"
                    android:textSize="15dp" />

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_centerVertical="true"
                    android:layout_toLeftOf="@id/tv_total_price"
                    android:text="合計金額:"
                    android:textColor="#555555"
                    android:textSize="13dp" />
            </RelativeLayout>

            <View
                android:layout_width="match_parent"
                android:layout_height="0.5dp"
                android:background="#cccccc" />
        </RelativeLayout>
    </LinearLayout>

    <RelativeLayout
        android:id="@+id/rl_no_contant"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:visibility="gone">

        <ImageView
            android:id="@+id/iv_no_contant"
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:layout_centerHorizontal="true"
            android:scaleType="centerCrop"
            android:src="@drawable/kong_gouwuche" />

        <TextView
            android:layout_width="200dp"
            android:layout_height="wrap_content"
            android:layout_below="@+id/iv_no_contant"
            android:layout_marginTop="20dp"
            android:gravity="center"
            android:text="購物車竟然是空的"
            android:textColor="#808080"
            android:textSize="16dp" />
    </RelativeLayout>

</RelativeLayout>
複製程式碼

2.購物車實現邏輯主介面(MainActivity.class)

package com.showly.yglin.shoppingcar;

import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.KeyEvent;
import android.view.View;
import android.widget.Button;
import android.widget.ExpandableListView;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import com.google.gson.Gson;
import com.showly.yglin.shoppingcar.adapter.ShoppingCarAdapter;
import com.showly.yglin.shoppingcar.bean.ShoppingCarDataBean;
import com.showly.yglin.shoppingcar.customview.RoundCornerDialog;
import com.showly.yglin.shoppingcar.util.ToastUtil;
import java.util.ArrayList;
import java.util.List;
import butterknife.ButterKnife;
import butterknife.InjectView;
import butterknife.OnClick;

/**
 * 購物車實現
 * 主要功能:
 *           1.單選、全選;
 *           2.合計;
 *           3.刪除;
 *           4.商品數量加減;
 */
public class MainActivity extends AppCompatActivity {

    @InjectView(R.id.tv_titlebar_center)
    TextView tvTitlebarCenter;
    @InjectView(R.id.tv_titlebar_right)
    TextView tvTitlebarRight;
    @InjectView(R.id.elv_shopping_car)
    ExpandableListView elvShoppingCar;
    @InjectView(R.id.iv_select_all)
    ImageView ivSelectAll;
    @InjectView(R.id.ll_select_all)
    LinearLayout llSelectAll;
    @InjectView(R.id.btn_order)
    Button btnOrder;
    @InjectView(R.id.btn_delete)
    Button btnDelete;
    @InjectView(R.id.tv_total_price)
    TextView tvTotalPrice;
    @InjectView(R.id.rl_total_price)
    RelativeLayout rlTotalPrice;
    @InjectView(R.id.rl)
    RelativeLayout rl;
    @InjectView(R.id.iv_no_contant)
    ImageView ivNoContant;
    @InjectView(R.id.rl_no_contant)
    RelativeLayout rlNoContant;
    @InjectView(R.id.tv_titlebar_left)
    ImageView tvTitlebarLeft;

    //模擬的購物車資料(實際開發中使用後臺返回的資料)
    private String shoppingCarData = "{\n" +
            "    \"code\": 200,\n" +
            "    \"datas\": [\n" +
            "        {\n" +
            "            \"goods\": [\n" +
            "                {\n" +
            "                    \"goods_id\": \"111111\",\n" +
            "                    \"goods_image\": \"http://pic.58pic.com/58pic/15/62/69/34K58PICbmZ_1024.jpg\",\n" +
            "                    \"goods_name\": \"三國演義\",\n" +
            "                    \"goods_num\": \"2\",\n" +
            "                    \"goods_price\": \"15.00\"\n" +
            "                }\n" +
            "            ],\n" +
            "            \"store_id\": \"1\",\n" +
            "            \"store_name\": \"書店雜貨鋪\"\n" +
            "        },\n" +
            "        {\n" +
            "            \"goods\": [\n" +
            "                {\n" +
            "                    \"goods_id\": \"222221\",\n" +
            "                    \"goods_image\": \"http://file06.16sucai.com/2016/0511/9711205e4c003182edeed83355e6f1c7.jpg\",\n" +
            "                    \"goods_name\": \"西遊記\",\n" +
            "                    \"goods_num\": \"2\",\n" +
            "                    \"goods_price\": \"12.00\"\n" +
            "                },\n" +
            "                {\n" +
            "                    \"goods_id\": \"222222\",\n" +
            "                    \"goods_image\": \"http://img01.taopic.com/150424/240473-1504240U13615.jpg\",\n" +
            "                    \"goods_name\": \"封神榜\",\n" +
            "                    \"goods_num\": \"1\",\n" +
            "                    \"goods_price\": \"28.00\"\n" +
            "                }\n" +
            "            ],\n" +
            "            \"store_id\": \"2\",\n" +
            "            \"store_name\": \"亞馬遜書店\"\n" +
            "        },\n" +
            "        {\n" +
            "            \"goods\": [\n" +
            "                {\n" +
            "                    \"goods_id\": \"333331\",\n" +
            "                    \"goods_image\": \"http://pic22.nipic.com/20120718/8002769_100147127333_2.jpg\",\n" +
            "                    \"goods_name\": \"水滸傳\",\n" +
            "                    \"goods_num\": \"3\",\n" +
            "                    \"goods_price\": \"18.00\"\n" +
            "                },\n" +
            "                {\n" +
            "                    \"goods_id\": \"333332\",\n" +
            "                    \"goods_image\": \"http://pic.58pic.com/58pic/14/71/50/40e58PICy54_1024.jpg\",\n" +
            "                    \"goods_name\": \"封神演義\",\n" +
            "                    \"goods_num\": \"3\",\n" +
            "                    \"goods_price\": \"32.00\"\n" +
            "                },\n" +
            "                {\n" +
            "                    \"goods_id\": \"333333\",\n" +
            "                    \"goods_image\": \"http://img01.taopic.com/150518/318750-15051PS40671.jpg\",\n" +
            "                    \"goods_name\": \"軒轅劍\",\n" +
            "                    \"goods_num\": \"3\",\n" +
            "                    \"goods_price\": \"3.80\"\n" +
            "                }\n" +
            "            ],\n" +
            "            \"store_id\": \"3\",\n" +
            "            \"store_name\": \"三味書屋\"\n" +
            "        }\n" +
            "    ]\n" +
            "}";
    private List<ShoppingCarDataBean.DatasBean> datas;
    private Context context;
    private ShoppingCarAdapter shoppingCarAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ButterKnife.inject(this);
        context = this;

        initExpandableListView();
        initData();
    }

    @OnClick({R.id.tv_titlebar_left, R.id.tv_titlebar_right})
    public void onViewClicked(View view) {
        switch (view.getId()) {
            case R.id.tv_titlebar_left://重新整理資料
                initData();
                break;
            case R.id.tv_titlebar_right://編輯
                String edit = tvTitlebarRight.getText().toString().trim();
                if (edit.equals("編輯")) {
                    tvTitlebarRight.setText("完成");
                    rlTotalPrice.setVisibility(View.GONE);
                    btnOrder.setVisibility(View.GONE);
                    btnDelete.setVisibility(View.VISIBLE);
                } else {
                    tvTitlebarRight.setText("編輯");
                    rlTotalPrice.setVisibility(View.VISIBLE);
                    btnOrder.setVisibility(View.VISIBLE);
                    btnDelete.setVisibility(View.GONE);
                }
                break;
            default:
                break;
        }
    }

    /**
     * 初始化資料
     */
    private void initData() {
        //使用Gson解析購物車資料,
        //ShoppingCarDataBean為bean類,Gson按照bean類的格式解析資料
        /**
         * 實際開發中,通過請求後臺介面獲取購物車資料並解析
         */
        Gson gson = new Gson();
        ShoppingCarDataBean shoppingCarDataBean = gson.fromJson(shoppingCarData, ShoppingCarDataBean.class);
        datas = shoppingCarDataBean.getDatas();

        initExpandableListViewData(datas);
    }

    /**
     * 初始化ExpandableListView
     * 建立資料介面卡adapter,並進行初始化操作
     */
    private void initExpandableListView() {
        shoppingCarAdapter = new ShoppingCarAdapter(context, llSelectAll, ivSelectAll, btnOrder, btnDelete, rlTotalPrice, tvTotalPrice);
        elvShoppingCar.setAdapter(shoppingCarAdapter);

        //刪除的回撥
        shoppingCarAdapter.setOnDeleteListener(new ShoppingCarAdapter.OnDeleteListener() {
            @Override
            public void onDelete() {
                initDelete();
                /**
                 * 實際開發中,在此請求刪除介面,刪除成功後,
                 * 通過initExpandableListViewData()方法重新整理購物車資料。
                 * 注:通過bean類中的DatasBean的isSelect_shop屬性,判斷店鋪是否被選中;
                 *                  GoodsBean的isSelect屬性,判斷商品是否被選中,
                 *                  (true為選中,false為未選中)
                 */
            }
        });

        //修改商品數量的回撥
        shoppingCarAdapter.setOnChangeCountListener(new ShoppingCarAdapter.OnChangeCountListener() {
            @Override
            public void onChangeCount(String goods_id) {
                /**
                 * 實際開發中,在此請求修改商品數量的介面,商品數量修改成功後,
                 * 通過initExpandableListViewData()方法重新整理購物車資料。
                 */
            }
        });
    }

    /**
     * 初始化ExpandableListView的資料
     * 並在資料重新整理時,頁面保持當前位置
     *
     * @param datas 購物車的資料
     */
    private void initExpandableListViewData(List<ShoppingCarDataBean.DatasBean> datas) {
        if (datas != null && datas.size() > 0) {
            //重新整理資料時,保持當前位置
            shoppingCarAdapter.setData(datas);

            //使所有組展開
            for (int i = 0; i < shoppingCarAdapter.getGroupCount(); i++) {
                elvShoppingCar.expandGroup(i);
            }

            //使組點選無效果
            elvShoppingCar.setOnGroupClickListener(new ExpandableListView.OnGroupClickListener() {

                @Override
                public boolean onGroupClick(ExpandableListView parent, View v,
                                            int groupPosition, long id) {
                    return true;
                }
            });

            tvTitlebarRight.setVisibility(View.VISIBLE);
            tvTitlebarRight.setText("編輯");
            rlNoContant.setVisibility(View.GONE);
            elvShoppingCar.setVisibility(View.VISIBLE);
            rl.setVisibility(View.VISIBLE);
            rlTotalPrice.setVisibility(View.VISIBLE);
            btnOrder.setVisibility(View.VISIBLE);
            btnDelete.setVisibility(View.GONE);
        } else {
            tvTitlebarRight.setVisibility(View.GONE);
            rlNoContant.setVisibility(View.VISIBLE);
            elvShoppingCar.setVisibility(View.GONE);
            rl.setVisibility(View.GONE);
        }
    }

    /**
     * 判斷是否要彈出刪除的dialog
     * 通過bean類中的DatasBean的isSelect_shop屬性,判斷店鋪是否被選中;
     * GoodsBean的isSelect屬性,判斷商品是否被選中,
     */
    private void initDelete() {
        //判斷是否有店鋪或商品被選中
        //true為有,則需要重新整理資料;反之,則不需要;
        boolean hasSelect = false;
        //建立臨時的List,用於儲存沒有被選中的購物車資料
        List<ShoppingCarDataBean.DatasBean> datasTemp = new ArrayList<>();

        for (int i = 0; i < datas.size(); i++) {
            List<ShoppingCarDataBean.DatasBean.GoodsBean> goods = datas.get(i).getGoods();
            boolean isSelect_shop = datas.get(i).getIsSelect_shop();

            if (isSelect_shop) {
                hasSelect = true;
                //跳出本次迴圈,繼續下次迴圈。
                continue;
            } else {
                datasTemp.add(datas.get(i));
                datasTemp.get(datasTemp.size() - 1).setGoods(new ArrayList<ShoppingCarDataBean.DatasBean.GoodsBean>());
            }

            for (int y = 0; y < goods.size(); y++) {
                ShoppingCarDataBean.DatasBean.GoodsBean goodsBean = goods.get(y);
                boolean isSelect = goodsBean.getIsSelect();

                if (isSelect) {
                    hasSelect = true;
                } else {
                    datasTemp.get(datasTemp.size() - 1).getGoods().add(goodsBean);
                }
            }
        }

        if (hasSelect) {
            showDeleteDialog(datasTemp);
        } else {
            ToastUtil.makeText(context, "請選擇要刪除的商品");
        }
    }

    /**
     * 展示刪除的dialog(可以自定義彈窗,不用刪除即可)
     *
     * @param datasTemp
     */
    private void showDeleteDialog(final List<ShoppingCarDataBean.DatasBean> datasTemp) {
        View view = View.inflate(context, R.layout.dialog_two_btn, null);
        final RoundCornerDialog roundCornerDialog = new RoundCornerDialog(context, 0, 0, view, R.style.RoundCornerDialog);
        roundCornerDialog.show();
        roundCornerDialog.setCanceledOnTouchOutside(false);// 設定點選螢幕Dialog不消失
        roundCornerDialog.setOnKeyListener(keylistener);//設定點選返回鍵Dialog不消失

        TextView tv_message =  view.findViewById(R.id.tv_message);
        TextView tv_logout_confirm = view.findViewById(R.id.tv_logout_confirm);
        TextView tv_logout_cancel =  view.findViewById(R.id.tv_logout_cancel);
        tv_message.setText("確定要刪除商品嗎?");

        //確定
        tv_logout_confirm.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                roundCornerDialog.dismiss();
                datas = datasTemp;
                initExpandableListViewData(datas);
            }
        });
        //取消
        tv_logout_cancel.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                roundCornerDialog.dismiss();
            }
        });
    }

    DialogInterface.OnKeyListener keylistener = new DialogInterface.OnKeyListener() {
        public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
            if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0) {
                return true;
            } else {
                return false;
            }
        }
    };
}


複製程式碼

3.使用ExpandableListView,繼承BaseExpandableListAdapter

package com.showly.yglin.shoppingcar.adapter;

import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseExpandableListAdapter;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import com.bumptech.glide.Glide;
import com.showly.yglin.shoppingcar.R;
import com.showly.yglin.shoppingcar.bean.ShoppingCarDataBean;
import com.showly.yglin.shoppingcar.util.ToastUtil;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;
import butterknife.ButterKnife;
import butterknife.InjectView;

/**
 * 購物車的adapter
 * 因為使用的是ExpandableListView,所以繼承BaseExpandableListAdapter
 */
public class ShoppingCarAdapter extends BaseExpandableListAdapter {

    private final Context context;
    private final LinearLayout llSelectAll;
    private final ImageView ivSelectAll;
    private final Button btnOrder;
    private final Button btnDelete;
    private final RelativeLayout rlTotalPrice;
    private final TextView tvTotalPrice;
    private List<ShoppingCarDataBean.DatasBean> data;
    private boolean isSelectAll = false;
    private double total_price;

    public ShoppingCarAdapter(Context context, LinearLayout llSelectAll,
                              ImageView ivSelectAll, Button btnOrder, Button btnDelete,
                              RelativeLayout rlTotalPrice, TextView tvTotalPrice) {
        this.context = context;
        this.llSelectAll = llSelectAll;
        this.ivSelectAll = ivSelectAll;
        this.btnOrder = btnOrder;
        this.btnDelete = btnDelete;
        this.rlTotalPrice = rlTotalPrice;
        this.tvTotalPrice = tvTotalPrice;
    }

    /**
     * 自定義設定資料方法;
     * 通過notifyDataSetChanged()重新整理資料,可保持當前位置
     *
     * @param data 需要重新整理的資料
     */
    public void setData(List<ShoppingCarDataBean.DatasBean> data) {
        this.data = data;
        notifyDataSetChanged();
    }

    @Override
    public int getGroupCount() {
        if (data != null && data.size() > 0) {
            return data.size();
        } else {
            return 0;
        }
    }

    @Override
    public Object getGroup(int groupPosition) {
        return data.get(groupPosition);
    }

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

    @Override
    public View getGroupView(final int groupPosition, final boolean isExpanded, View convertView, ViewGroup parent) {
        GroupViewHolder groupViewHolder;
        if (convertView == null) {
            convertView = View.inflate(context, R.layout.item_shopping_car_group, null);

            groupViewHolder = new GroupViewHolder(convertView);
            convertView.setTag(groupViewHolder);
        } else {
            groupViewHolder = (GroupViewHolder) convertView.getTag();
        }
        final ShoppingCarDataBean.DatasBean datasBean = data.get(groupPosition);
        //店鋪ID
        String store_id = datasBean.getStore_id();
        //店鋪名稱
        String store_name = datasBean.getStore_name();

        if (store_name != null) {
            groupViewHolder.tvStoreName.setText(store_name);
        } else {
            groupViewHolder.tvStoreName.setText("");
        }

        //店鋪內的商品都選中的時候,店鋪的也要選中
        for (int i = 0; i < datasBean.getGoods().size(); i++) {
            ShoppingCarDataBean.DatasBean.GoodsBean goodsBean = datasBean.getGoods().get(i);
            boolean isSelect = goodsBean.getIsSelect();
            if (isSelect) {
                datasBean.setIsSelect_shop(true);
            } else {
                datasBean.setIsSelect_shop(false);
                break;
            }
        }

        //因為set之後要重新get,所以這一塊程式碼要放到一起執行
        //店鋪是否在購物車中被選中
        final boolean isSelect_shop = datasBean.getIsSelect_shop();
        if (isSelect_shop) {
            groupViewHolder.ivSelect.setImageResource(R.drawable.xuanze_xuanzhong);
        } else {
            groupViewHolder.ivSelect.setImageResource(R.drawable.unselect);
        }

        //店鋪選擇框的點選事件
        groupViewHolder.ll.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                datasBean.setIsSelect_shop(!isSelect_shop);

                List<ShoppingCarDataBean.DatasBean.GoodsBean> goods = datasBean.getGoods();
                for (int i = 0; i < goods.size(); i++) {
                    ShoppingCarDataBean.DatasBean.GoodsBean goodsBean = goods.get(i);
                    goodsBean.setIsSelect(!isSelect_shop);
                }
                notifyDataSetChanged();
            }
        });

        //當所有的選擇框都是選中的時候,全選也要選中
        w:
        for (int i = 0; i < data.size(); i++) {
            List<ShoppingCarDataBean.DatasBean.GoodsBean> goods = data.get(i).getGoods();
            for (int y = 0; y < goods.size(); y++) {
                ShoppingCarDataBean.DatasBean.GoodsBean goodsBean = goods.get(y);
                boolean isSelect = goodsBean.getIsSelect();
                if (isSelect) {
                    isSelectAll = true;
                } else {
                    isSelectAll = false;
                    break w;//根據標記,跳出巢狀迴圈
                }
            }
        }
        if (isSelectAll) {
            ivSelectAll.setBackgroundResource(R.drawable.xuanze_xuanzhong);
        } else {
            ivSelectAll.setBackgroundResource(R.drawable.unselect);
        }

        //全選的點選事件
        llSelectAll.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                isSelectAll = !isSelectAll;

                if (isSelectAll) {
                    for (int i = 0; i < data.size(); i++) {
                        List<ShoppingCarDataBean.DatasBean.GoodsBean> goods = data.get(i).getGoods();
                        for (int y = 0; y < goods.size(); y++) {
                            ShoppingCarDataBean.DatasBean.GoodsBean goodsBean = goods.get(y);
                            goodsBean.setIsSelect(true);
                        }
                    }
                } else {
                    for (int i = 0; i < data.size(); i++) {
                        List<ShoppingCarDataBean.DatasBean.GoodsBean> goods = data.get(i).getGoods();
                        for (int y = 0; y < goods.size(); y++) {
                            ShoppingCarDataBean.DatasBean.GoodsBean goodsBean = goods.get(y);
                            goodsBean.setIsSelect(false);
                        }
                    }
                }
                notifyDataSetChanged();
            }
        });

        //合計的計算
        total_price = 0.0;
        tvTotalPrice.setText("¥0.00");
        for (int i = 0; i < data.size(); i++) {
            List<ShoppingCarDataBean.DatasBean.GoodsBean> goods = data.get(i).getGoods();
            for (int y = 0; y < goods.size(); y++) {
                ShoppingCarDataBean.DatasBean.GoodsBean goodsBean = goods.get(y);
                boolean isSelect = goodsBean.getIsSelect();
                if (isSelect) {
                    String num = goodsBean.getGoods_num();
                    String price = goodsBean.getGoods_price();

                    double v = Double.parseDouble(num);
                    double v1 = Double.parseDouble(price);

                    total_price = total_price + v * v1;

                    //讓Double型別完整顯示,不用科學計數法顯示大寫字母E
                    DecimalFormat decimalFormat = new DecimalFormat("0.00");
                    tvTotalPrice.setText("¥" + decimalFormat.format(total_price));
                }
            }
        }

        //去結算的點選事件
        btnOrder.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //建立臨時的List,用於儲存被選中的商品
                List<ShoppingCarDataBean.DatasBean.GoodsBean> temp = new ArrayList<>();
                for (int i = 0; i < data.size(); i++) {
                    List<ShoppingCarDataBean.DatasBean.GoodsBean> goods = data.get(i).getGoods();
                    for (int y = 0; y < goods.size(); y++) {
                        ShoppingCarDataBean.DatasBean.GoodsBean goodsBean = goods.get(y);
                        boolean isSelect = goodsBean.getIsSelect();
                        if (isSelect) {
                            temp.add(goodsBean);
                        }
                    }
                }

                if (temp != null && temp.size() > 0) {//如果有被選中的
                    /**
                     * 實際開發中,如果有被選中的商品,
                     * 則跳轉到確認訂單頁面,完成後續訂單流程。
                     */
                    ToastUtil.makeText(context, "跳轉到確認訂單頁面,完成後續訂單流程");
                } else {
                    ToastUtil.makeText(context, "請選擇要購買的商品");
                }
            }
        });

        //刪除的點選事件
        btnDelete.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                /**
                 * 實際開發中,通過回撥請求後臺介面實現刪除操作
                 */
                if (mDeleteListener != null) {
                    mDeleteListener.onDelete();
                }
            }
        });

        return convertView;
    }

    static class GroupViewHolder {
        @InjectView(R.id.iv_select)
        ImageView ivSelect;
        @InjectView(R.id.tv_store_name)
        TextView tvStoreName;
        @InjectView(R.id.ll)
        LinearLayout ll;

        GroupViewHolder(View view) {
            ButterKnife.inject(this, view);
        }
    }

    //------------------------------------------------------------------------------------------------
    @Override
    public int getChildrenCount(int groupPosition) {
        if (data.get(groupPosition).getGoods() != null && data.get(groupPosition).getGoods().size() > 0) {
            return data.get(groupPosition).getGoods().size();
        } else {
            return 0;
        }
    }

    @Override
    public Object getChild(int groupPosition, int childPosition) {
        return data.get(groupPosition).getGoods().get(childPosition);
    }

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

    @Override
    public View getChildView(final int groupPosition, final int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
        ChildViewHolder childViewHolder;
        if (convertView == null) {
            convertView = View.inflate(context, R.layout.item_shopping_car_child, null);

            childViewHolder = new ChildViewHolder(convertView);
            convertView.setTag(childViewHolder);
        } else {
            childViewHolder = (ChildViewHolder) convertView.getTag();
        }
        final ShoppingCarDataBean.DatasBean datasBean = data.get(groupPosition);
        //店鋪ID
        String store_id = datasBean.getStore_id();
        //店鋪名稱
        String store_name = datasBean.getStore_name();
        //店鋪是否在購物車中被選中
        final boolean isSelect_shop = datasBean.getIsSelect_shop();
        final ShoppingCarDataBean.DatasBean.GoodsBean goodsBean = datasBean.getGoods().get(childPosition);
        //商品圖片
        String goods_image = goodsBean.getGoods_image();
        //商品ID
        final String goods_id = goodsBean.getGoods_id();
        //商品名稱
        String goods_name = goodsBean.getGoods_name();
        //商品價格
        String goods_price = goodsBean.getGoods_price();
        //商品數量
        String goods_num = goodsBean.getGoods_num();
        //商品是否被選中
        final boolean isSelect = goodsBean.getIsSelect();

        Glide.with(context)
                .load(R.drawable.img)
                .into(childViewHolder.ivPhoto);
        if (goods_name != null) {
            childViewHolder.tvName.setText(goods_name);
        } else {
            childViewHolder.tvName.setText("");
        }
        if (goods_price != null) {
            childViewHolder.tvPriceValue.setText(goods_price);
        } else {
            childViewHolder.tvPriceValue.setText("");
        }
        if (goods_num != null) {
            childViewHolder.tvEditBuyNumber.setText(goods_num);
        } else {
            childViewHolder.tvEditBuyNumber.setText("");
        }

        //商品是否被選中
        if (isSelect) {
            childViewHolder.ivSelect.setImageResource(R.drawable.xuanze_xuanzhong);
        } else {
            childViewHolder.ivSelect.setImageResource(R.drawable.unselect);
        }

        //商品選擇框的點選事件
        childViewHolder.ivSelect.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                goodsBean.setIsSelect(!isSelect);
                if (!isSelect == false) {
                    datasBean.setIsSelect_shop(false);
                }
                notifyDataSetChanged();
            }
        });

        //加號的點選事件
        childViewHolder.ivEditAdd.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //模擬加號操作
                String num = goodsBean.getGoods_num();
                Integer integer = Integer.valueOf(num);
                integer++;
                goodsBean.setGoods_num(integer + "");
                notifyDataSetChanged();

                /**
                 * 實際開發中,通過回撥請求後臺介面實現數量的加減
                 */
                if (mChangeCountListener != null) {
                    mChangeCountListener.onChangeCount(goods_id);
                }
            }
        });
        //減號的點選事件
        childViewHolder.ivEditSubtract.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //模擬減號操作
                String num = goodsBean.getGoods_num();
                Integer integer = Integer.valueOf(num);
                if (integer > 1) {
                    integer--;
                    goodsBean.setGoods_num(integer + "");

                    /**
                     * 實際開發中,通過回撥請求後臺介面實現數量的加減
                     */
                    if (mChangeCountListener != null) {
                        mChangeCountListener.onChangeCount(goods_id);
                    }
                } else {
                    ToastUtil.makeText(context, "商品不能再減少了");
                }
                notifyDataSetChanged();
            }
        });

        if (childPosition == data.get(groupPosition).getGoods().size() - 1) {
            childViewHolder.view.setVisibility(View.GONE);
            childViewHolder.viewLast.setVisibility(View.VISIBLE);
        } else {
            childViewHolder.view.setVisibility(View.VISIBLE);
            childViewHolder.viewLast.setVisibility(View.GONE);
        }

        return convertView;
    }

    static class ChildViewHolder {
        @InjectView(R.id.iv_select)
        ImageView ivSelect;
        @InjectView(R.id.iv_photo)
        ImageView ivPhoto;
        @InjectView(R.id.tv_name)
        TextView tvName;
        @InjectView(R.id.tv_price_key)
        TextView tvPriceKey;
        @InjectView(R.id.tv_price_value)
        TextView tvPriceValue;
        @InjectView(R.id.iv_edit_subtract)
        ImageView ivEditSubtract;
        @InjectView(R.id.tv_edit_buy_number)
        TextView tvEditBuyNumber;
        @InjectView(R.id.iv_edit_add)
        ImageView ivEditAdd;
        @InjectView(R.id.view)
        View view;
        @InjectView(R.id.view_last)
        View viewLast;

        ChildViewHolder(View view) {
            ButterKnife.inject(this, view);
        }
    }

    //-----------------------------------------------------------------------------------------------

    @Override
    public boolean isChildSelectable(int groupPosition, int childPosition) {
        return false;
    }

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

    //刪除的回撥
    public interface OnDeleteListener {
        void onDelete();
    }

    public void setOnDeleteListener(OnDeleteListener listener) {
        mDeleteListener = listener;
    }

    private OnDeleteListener mDeleteListener;

    //修改商品數量的回撥
    public interface OnChangeCountListener {
        void onChangeCount(String goods_id);
    }

    public void setOnChangeCountListener(OnChangeCountListener listener) {
        mChangeCountListener = listener;
    }

    private OnChangeCountListener mChangeCountListener;
}

複製程式碼

4.購物車資料的bean類(ShoppingCarDataBean.class)

package com.showly.yglin.shoppingcar.bean;

import java.util.List;

/**
 * 購物車資料的bean類
 */

public class ShoppingCarDataBean {

    private int code;
    private List<DatasBean> datas;

    public int getCode() {
        return code;
    }

    public void setCode(int code) {
        this.code = code;
    }

    public List<DatasBean> getDatas() {
        return datas;
    }

    public void setDatas(List<DatasBean> datas) {
        this.datas = datas;
    }

    public static class DatasBean {

        private String store_id;
        private String store_name;
        private boolean isSelect_shop;      //店鋪是否在購物車中被選中
        private List<GoodsBean> goods;

        public boolean getIsSelect_shop() {
            return isSelect_shop;
        }

        public void setIsSelect_shop(boolean select_shop) {
            isSelect_shop = select_shop;
        }

        public String getStore_id() {
            return store_id;
        }

        public void setStore_id(String store_id) {
            this.store_id = store_id;
        }

        public String getStore_name() {
            return store_name;
        }

        public void setStore_name(String store_name) {
            this.store_name = store_name;
        }

        public List<GoodsBean> getGoods() {
            return goods;
        }

        public void setGoods(List<GoodsBean> goods) {
            this.goods = goods;
        }

        public static class GoodsBean {

            private String goods_id;
            private String goods_image;
            private String goods_name;
            private String goods_num;
            private String goods_price;
            private boolean isSelect;        //商品是否在購物車中被選中

            public boolean getIsSelect() {
                return isSelect;
            }

            public void setIsSelect(boolean isSelect) {
                this.isSelect = isSelect;
            }

            public String getGoods_id() {
                return goods_id;
            }

            public void setGoods_id(String goods_id) {
                this.goods_id = goods_id;
            }

            public String getGoods_image() {
                return goods_image;
            }

            public void setGoods_image(String goods_image) {
                this.goods_image = goods_image;
            }

            public String getGoods_name() {
                return goods_name;
            }

            public void setGoods_name(String goods_name) {
                this.goods_name = goods_name;
            }

            public String getGoods_num() {
                return goods_num;
            }

            public void setGoods_num(String goods_num) {
                this.goods_num = goods_num;
            }

            public String getGoods_price() {
                return goods_price;
            }

            public void setGoods_price(String goods_price) {
                this.goods_price = goods_price;
            }
        }
    }
}

複製程式碼

5.分店鋪實現佈局

效果圖(紅色部分):

在這裡插入圖片描述

<?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:background="#ffffff"
    android:orientation="vertical">

    <LinearLayout
        android:id="@+id/ll"
        android:layout_width="match_parent"
        android:layout_height="40dp"
        android:orientation="horizontal">

        <ImageView
            android:id="@+id/iv_select"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_vertical"
            android:layout_marginLeft="10dp"
            android:background="@drawable/unselect" />

        <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_vertical"
            android:layout_marginLeft="10dp"
            android:background="@drawable/biaoqianlan_kefu" />

        <TextView
            android:id="@+id/tv_store_name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_marginLeft="10dp"
            android:text="店鋪名稱"
            android:textColor="#333333"
            android:textSize="14dp"
            android:maxLines="1"
            android:ellipsize="end"/>
    </LinearLayout>

    <View
        android:layout_width="match_parent"
        android:layout_height="0.5dp"
        android:layout_marginLeft="10dp"
        android:background="#cccccc" />
</LinearLayout>
複製程式碼

6.購物車中商品Item佈局檔案 效果圖:

在這裡插入圖片描述

<?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"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="#ffffff"
    android:orientation="vertical">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="100dp"
        android:background="#ffffff">

        <ImageView
            android:id="@+id/iv_select"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_gravity="center_vertical"
            android:padding="10dp"
            android:src="@drawable/unselect" />

        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent">

            <ImageView
                android:id="@+id/iv_photo"
                android:layout_width="90dp"
                android:layout_height="90dp"
                android:layout_centerVertical="true"
                android:background="#ededed"
                android:scaleType="centerCrop" />

            <TextView
                android:id="@+id/tv_name"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginLeft="10dp"
                android:layout_marginRight="10dp"
                android:layout_marginTop="10dp"
                android:layout_toRightOf="@id/iv_photo"
                android:ellipsize="end"
                android:maxLines="2"
                android:text="時空房間啊連結法蘭克福驕傲拉開飛機阿里進來撒劫匪了卡減肥了看見拉殺劫匪垃圾費垃圾費啦"
                android:textColor="#333333"
                android:textSize="14dp" />

            <RelativeLayout
                android:layout_width="match_parent"
                android:layout_height="35dp"
                android:layout_alignParentBottom="true"
                android:layout_marginLeft="10dp"
                android:layout_toRightOf="@id/iv_photo">

                <TextView
                    android:id="@+id/tv_price_key"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_centerVertical="true"
                    android:text="¥"
                    android:textColor="#ee1d23"
                    android:textSize="12dp" />

                <TextView
                    android:id="@+id/tv_price_value"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_centerVertical="true"
                    android:layout_marginLeft="2dp"
                    android:layout_toRightOf="@id/tv_price_key"
                    android:text="499"
                    android:textColor="#ee1d23"
                    android:textSize="14dp" />

                <LinearLayout
                    android:layout_width="wrap_content"
                    android:layout_height="match_parent"
                    android:layout_alignParentRight="true"
                    android:layout_centerVertical="true"
                    android:gravity="center"
                    android:orientation="horizontal">

                    <ImageView
                        android:id="@+id/iv_edit_subtract"
                        android:layout_width="wrap_content"
                        android:layout_height="match_parent"
                        android:paddingLeft="15dp"
                        android:paddingRight="15dp"
                        android:src="@drawable/iv_edit_subtract" />

                    <TextView
                        android:id="@+id/tv_edit_buy_number"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:gravity="center"
                        android:minEms="1"
                        android:text="1"
                        android:textColor="#666666"
                        android:textSize="12dp" />

                    <ImageView
                        android:id="@+id/iv_edit_add"
                        android:layout_width="wrap_content"
                        android:layout_height="match_parent"
                        android:paddingLeft="15dp"
                        android:paddingRight="15dp"
                        android:src="@drawable/iv_edit_add" />
                </LinearLayout>

                <View
                    android:id="@+id/view"
                    android:layout_width="match_parent"
                    android:layout_height="0.5dp"
                    android:layout_alignParentBottom="true"
                    android:background="#cccccc" />
            </RelativeLayout>
        </RelativeLayout>
    </LinearLayout>

    <View
        android:id="@+id/view_last"
        android:layout_width="match_parent"
        android:layout_height="10dp"
        android:layout_alignParentBottom="true"
        android:background="#ededed"
        android:visibility="gone" />
</LinearLayout>
複製程式碼

自此,購物車的功能基本已經實現了

Demo:底部公眾號回覆"購物車功能"即可獲取。

以下是個人公眾號(longxuanzhigu),之後釋出的文章會同步到該公眾號,方便交流學習Android知識及分享個人愛好文章:

在這裡插入圖片描述

相關文章