首先在values文件夹下创建一个dimens文件:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<dimen name="left_space_pading">12dp</dimen>
</resources>
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="com.example.cart_demo.MainActivity">
<ExpandableListView
android:id="@+id/elv_cart"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="60dp">
</ExpandableListView>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="60dp"
android:layout_alignParentBottom="true"
android:background="#eeeeee"
android:gravity="center_vertical"
>
<CheckBox
android:id="@+id/ck_cart_all_select"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="全选"
/>
<TextView
android:id="@+id/tv_cart_total_price"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:paddingLeft="20dp"
android:text="合计:¥0.00"
/>
<Button
android:id="@+id/btn_cart_pay"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="去结算(0)"
android:background="#ff0000"
android:textColor="#fff"
/>
</LinearLayout>
</RelativeLayout>
二级列表的父布局 —— cart_parent_item_layout.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"
android:layout_height="60dp"
android:gravity="center_vertical"
android:paddingLeft="@dimen/left_space_pading"
>
<CheckBox
android:id="@+id/seller_ck"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="15dp"/>
<TextView
android:id="@+id/seller_name_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
/>
</LinearLayout>
二级列表的子布局 —— cart_child_item_layout.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"
android:layout_height="120dp"
android:gravity="center_vertical"
android:paddingLeft="@dimen/left_space_pading"
>
<CheckBox
android:id="@+id/child_ck"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<ImageView
android:id="@+id/product_icon_iv"
android:layout_width="80dp"
android:layout_height="80dp"
android:layout_marginLeft="20dp"
android:scaleType="centerCrop"
android:src="@color/colorPrimary"
/>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="@dimen/left_space_pading"
android:orientation="vertical"
android:layout_weight="1">
<TextView
android:id="@+id/product_title_name_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:maxLines="2"
android:text="商品标题"
/>
<TextView
android:id="@+id/product_price_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:text="¥0.0"
/>
</LinearLayout>
<com.example.cart_demo.MyAddSubView
android:id="@+id/add_remove_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="10dp"
></com.example.cart_demo.MyAddSubView>
</LinearLayout>
然后自定义加减器的布局 —— add_remove_view_layout.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="60dp"
android:layout_height="30dp"
android:padding="2dp"
android:layout_marginLeft="10dp"
android:layout_gravity="center_vertical"
android:background="#99000000"
android:gravity="center_vertical">
<TextView
android:id="@+id/sub_tv"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="#ffffff"
android:gravity="center"
android:text="-"
android:textSize="16sp"
/>
<TextView
android:id="@+id/product_number_tv"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:layout_marginLeft="2dp"
android:gravity="center"
android:background="#ffffff"
android:text="1"
/>
<TextView
android:id="@+id/add_tv"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="#ffffff"
android:gravity="center"
android:layout_marginLeft="2dp"
android:text="+"
android:textSize="16sp"
/>
</LinearLayout>
布局到这就ok了,随后就是自定义加减器的实现 —— MyAddSubView:
package com.example.cart_demo;
import android.content.Context;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
/**
* Created by DELL on 2018/6/29.
*/
public class MyAddSubView extends LinearLayout implements View.OnClickListener {
private TextView sub_tv;
private TextView product_number_tv;
private TextView add_tv;
private int num = 1;
public MyAddSubView(Context context) {
this(context, null);
}
public MyAddSubView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
View view = inflate(context, R.layout.add_remove_view_layout, this);
sub_tv = view.findViewById(R.id.sub_tv);
product_number_tv = view.findViewById(R.id.product_number_tv);
add_tv = view.findViewById(R.id.add_tv);
sub_tv.setOnClickListener(this);
add_tv.setOnClickListener(this);
}
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.sub_tv:
if (num > 1) {
--num;
product_number_tv.setText(num + "");
if (onNumChangerListener != null) {
onNumChangerListener.onNumChange(num);
} else {
Toast.makeText(getContext(), "商品数量不能小于1", Toast.LENGTH_SHORT).show();
}
}
break;
case R.id.add_tv:
++num;
product_number_tv.setText(num + "");
if (onNumChangerListener != null) {
onNumChangerListener.onNumChange(num);
}
break;
}
}
public int getNum() {
return num;
}
public void setNum(int num) {
this.num = num;
product_number_tv.setText(num + "");
}
private OnNumChangerListener onNumChangerListener;
public void setOnNumChangerListener(OnNumChangerListener onNumChangerListener) {
this.onNumChangerListener = onNumChangerListener;
}
interface OnNumChangerListener {
void onNumChange(int number);
}
}
接下来核心的东西来了 —— MAdapter(二级列表的适配器):
package com.example.cart_demo;
import android.content.Context;
import android.graphics.Bitmap;
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.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.assist.ImageScaleType;
import java.util.List;
/**
* Created by DELL on 2018/6/29.
*/
public class MAdapter extends BaseExpandableListAdapter {
private Context context;
private List<Carts.DataBean> list;
private final DisplayImageOptions options;
public MAdapter(Context context, List<Carts.DataBean> list) {
this.context = context;
this.list = list;
options = new DisplayImageOptions.Builder()
.cacheInMemory(true)//使用内存缓存
.cacheOnDisk(true)//使用磁盘缓存
.bitmapConfig(Bitmap.Config.RGB_565)//设置图片色彩模式
.imageScaleType(ImageScaleType.EXACTLY)//设置图片的缩放模式
.build();
}
@Override
public int getGroupCount() {
return list == null ? 0 : list.size();
}
@Override
public int getChildrenCount(int i) {
return list.get(i).getList() == null ? 0 : list.get(i).getList().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 View getGroupView(final int i, boolean b, View view, ViewGroup viewGroup) {
ParentViewHolder parentHolder = null;
if (view == null) {
view = View.inflate(context, R.layout.cart_parent_item_layout, null);
parentHolder = new ParentViewHolder();
parentHolder.seller_ck = (CheckBox) view.findViewById(R.id.seller_ck);
parentHolder.seller_name_tv = (TextView) view.findViewById(R.id.seller_name_tv);
view.setTag(parentHolder);
} else {
parentHolder = (ParentViewHolder) view.getTag();
}
parentHolder.seller_name_tv.setText(list.get(i).getSellerName());
boolean currentSellerAllProductSelected = isCurrentSellerAllProductSelected(i);
parentHolder.seller_ck.setChecked(currentSellerAllProductSelected);
parentHolder.seller_ck.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if(onCartListChangeListener != null){
onCartListChangeListener.onSellerCheckedChange(i);
}
}
});
return view;
}
//判断当前商家所有商品是否被选中
public boolean isCurrentSellerAllProductSelected(int i) {
Carts.DataBean dataBean = list.get(i);
List<Carts.DataBean.ListBean> list1 = dataBean.getList();
//List<Carts.DataBean.ListBean> list = this.list.get(i).getList();
for (Carts.DataBean.ListBean listBean : list1) {
if (listBean.getSelected() == 0) {
return false;
}
}
return true;
}
@Override
public View getChildView(final int i, final int i1, boolean b, View view, ViewGroup viewGroup) {
Carts.DataBean dataBean = list.get(i);
List<Carts.DataBean.ListBean> list = dataBean.getList();
Carts.DataBean.ListBean listBean = list.get(i1);
ChildViewHolder childHolder = null;
if (view == null) {
view = View.inflate(context, R.layout.cart_child_item_layout, null);
childHolder = new ChildViewHolder();
childHolder.child_ck = (CheckBox) view.findViewById(R.id.child_ck);
childHolder.product_icon_iv = (ImageView) view.findViewById(R.id.product_icon_iv);
childHolder.product_title_name_tv = (TextView) view.findViewById(R.id.product_title_name_tv);
childHolder.product_price_tv = (TextView) view.findViewById(R.id.product_price_tv);
childHolder.add_remove_view = (MyAddSubView) view.findViewById(R.id.add_remove_view);
view.setTag(childHolder);
} else {
childHolder = (ChildViewHolder) view.getTag();
}
//商品名称
childHolder.product_title_name_tv.setText(listBean.getTitle());
//商品单价
childHolder.product_price_tv.setText(listBean.getPrice() + "");
String[] strings = listBean.getImages().split("\\|");
ImageLoader.getInstance().displayImage(strings[0],childHolder.product_icon_iv,options);
childHolder.child_ck.setChecked(listBean.getSelected() == 1);
childHolder.child_ck.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if(onCartListChangeListener != null){
onCartListChangeListener.onProductCheckedChange(i,i1);
}
}
});
childHolder.add_remove_view.setNum(listBean.getNum());
childHolder.add_remove_view.setOnNumChangerListener(new MyAddSubView.OnNumChangerListener() {
@Override
public void onNumChange(int number) {
if(onCartListChangeListener != null){
onCartListChangeListener.onProductNumberChange(i,i1,number);
}
}
});
return view;
}
@Override
public boolean isChildSelectable(int i, int i1) {
return false;
}
//所有商品是否被选中
public boolean isAllProductsSelected() {
for (int i = 0; i < list.size(); i++) {
Carts.DataBean dataBean = list.get(i);
List<Carts.DataBean.ListBean> list = dataBean.getList();
for (int j = 0; j < list.size(); j++) {
if (list.get(j).getSelected() == 0) {
return false;
}
}
}
return true;
}
//计算总价
public float calculateTotalPrice(){
float totalPrice = 0;
for (int i = 0; i < list.size(); i++) {
Carts.DataBean dataBean = list.get(i);
List<Carts.DataBean.ListBean> list = dataBean.getList();
for (int j = 0; j < list.size(); j++) {
if(list.get(j).getSelected() == 1){
float price = list.get(j).getPrice();
int num = list.get(j).getNum();
totalPrice += price * num;
}
}
}
return totalPrice;
}
public int calculateTotalNumber(){
int totalNumber = 0;
for (int i = 0; i < list.size(); i++) {
Carts.DataBean dataBean = list.get(i);
List<Carts.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;
}
//当商家得checkbox被点击得时候调用,设置当前商家得所有商品得状态
public void changeCurrentSellerAllProductsStatus(int i, boolean isSelected){
Carts.DataBean dataBean = list.get(i);
List<Carts.DataBean.ListBean> list = dataBean.getList();
for (int j = 0; j < list.size(); j++) {
Carts.DataBean.ListBean listBean = list.get(j);
listBean.setSelected(isSelected ? 1 : 0);
}
}
//当商品得checkbox被点击得时候调用,改变当前商品状态
public void changeCurrentProductStatus(int i, int i1){
Carts.DataBean dataBean = list.get(i);
List<Carts.DataBean.ListBean> list = dataBean.getList();
Carts.DataBean.ListBean listBean = list.get(i1);
listBean.setSelected(listBean.getSelected() == 0 ? 1 : 0);
}
//当加减器被点击得时候调用,改变当前商品得数量
public void changeCurrentProductNumber(int i, int i1, int number){
Carts.DataBean dataBean = list.get(i);
List<Carts.DataBean.ListBean> list = dataBean.getList();
Carts.DataBean.ListBean listBean = list.get(i1);
listBean.setNum(number);
}
//设置所有商品得状态
public void changeAllProductsStatus(boolean selected){
for (int i = 0; i < list.size(); i++) {
Carts.DataBean dataBean = list.get(i);
List<Carts.DataBean.ListBean> list = dataBean.getList();
for (int j = 0; j < list.size(); j++) {
list.get(j).setSelected(selected ? 1 : 0);
}
}
}
class ParentViewHolder {
public CheckBox seller_ck;
public TextView seller_name_tv;
}
class ChildViewHolder {
public CheckBox child_ck;
public ImageView product_icon_iv;
public TextView product_title_name_tv;
public TextView product_price_tv;
public MyAddSubView add_remove_view;
}
private OnCartListChangeListener onCartListChangeListener;
public void setOnCartListChangeListener(OnCartListChangeListener onCartListChangeListener){
this.onCartListChangeListener = onCartListChangeListener;
}
public interface OnCartListChangeListener{
void onSellerCheckedChange(int i);
void onProductCheckedChange(int i, int i1);
void onProductNumberChange(int i, int i1, int number);
}
}
最后MainActivity的实现:
package com.example.cart_demo;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.ExpandableListView;
import android.widget.TextView;
import com.google.gson.Gson;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class MainActivity extends AppCompatActivity {
private ExpandableListView elv_cart;
private CheckBox ck_cart_all_select;
private TextView tv_cart_total_price;
private Button btn_cart_pay;
private MAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
initData();
}
private void initData() {
String url = "https://www.zhaoapi.cn/product/getCarts";
Map<String, String> map = new HashMap<>();
map.put("uid", "71");
OkhttpUtils.getInstance().doPost(url, map, new OkhttpUtils.OkCallback() {
@Override
public void onResponse(String json) {
Gson gson = new Gson();
Carts carts = gson.fromJson(json, Carts.class);
String code = carts.getCode();
if ("0".equalsIgnoreCase(code)) {
List<Carts.DataBean> data = carts.getData();
adapter = new MAdapter(MainActivity.this, data);
adapter.setOnCartListChangeListener(new MAdapter.OnCartListChangeListener() {
@Override
public void onSellerCheckedChange(int i) {
boolean currentSellerAllProductSelected = adapter.isCurrentSellerAllProductSelected(i);
adapter.changeCurrentSellerAllProductsStatus(i, !currentSellerAllProductSelected);
adapter.notifyDataSetChanged();
//刷新底部数据
refreshSelectedAndTotalPriceAndTotalNumber();
}
@Override
public void onProductCheckedChange(int i, int i1) {
adapter.changeCurrentProductStatus(i, i1);
adapter.notifyDataSetChanged();
//刷新底部数据
refreshSelectedAndTotalPriceAndTotalNumber();
}
@Override
public void onProductNumberChange(int i, int i1, int number) {
adapter.changeCurrentProductNumber(i, i1, number);
adapter.notifyDataSetChanged();
//刷新底部数据
refreshSelectedAndTotalPriceAndTotalNumber();
}
});
elv_cart.setAdapter(adapter);
//展开二级列表
for (int i = 0; i < data.size(); i++) {
elv_cart.expandGroup(i);
}
//刷新底部数据
refreshSelectedAndTotalPriceAndTotalNumber();
}
}
@Override
public void onFailure(Exception e) {
}
});
}
//刷新checkbox状态和总价和总数量
private void refreshSelectedAndTotalPriceAndTotalNumber() {
//判断是否所有的商品都被选中
boolean allProductsSelected = adapter.isAllProductsSelected();
ck_cart_all_select.setChecked(allProductsSelected);
//计算总价
float price = adapter.calculateTotalPrice();
tv_cart_total_price.setText("总价:" + price);
//计算总数量
int i = adapter.calculateTotalNumber();
btn_cart_pay.setText("去结算(" + i + ")");
}
private void initView() {
elv_cart = findViewById(R.id.elv_cart);
ck_cart_all_select = findViewById(R.id.ck_cart_all_select);
tv_cart_total_price = findViewById(R.id.tv_cart_total_price);
btn_cart_pay = findViewById(R.id.btn_cart_pay);
ck_cart_all_select.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
boolean allProductsSelected = adapter.isAllProductsSelected();
adapter.changeAllProductsStatus(!allProductsSelected);
adapter.notifyDataSetChanged();
//刷新底部数据
refreshSelectedAndTotalPriceAndTotalNumber();
}
});
}
}