首先先看一下我的效果图: 是不是感觉挺不错的呀!下面教一下大家实现的方式
因为我是网络请求的数据,所以先添加依赖:
compile 'com.squareup.okio:okio:1.5.0'网络请求是我自己封装的okhttp3,所以在这我就不写这段代码了,各位根据自己的需求封装网络请求就可以了
compile 'com.squareup.okhttp3:okhttp:3.2.0'compile 'com.squareup.okhttp3:logging-interceptor:3.4.1'compile 'com.squareup.picasso:picasso:2.5.1' compile 'com.google.code.gson:gson:2.8.1' 下面先进行布局设置,也就是配置相对于的xml文件,请看代码: 在res下的layout创建3个.xml文件: 主页面: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="@android:color/darker_gray" > <ScrollView android:layout_width="match_parent" android:layout_height="match_parent" android:layout_marginBottom="51dp" > <com.weiyuhui.ShoppingCart_01.view.CustomExpandableListView android:id="@+id/celv" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#fff" > </com.weiyuhui.ShoppingCart_01.view.CustomExpandableListView> </ScrollView> <RelativeLayout android:layout_width="match_parent" android:layout_height="50dp" android:layout_alignParentBottom="true" android:background="@android:color/white" android:gravity="center_vertical" > <CheckBox android:id="@+id/checkbox2" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_gravity="center_vertical" android:layout_marginLeft="15dp" android:drawablePadding="5dp" android:text="全选" android:textColor="#6b6868" /> <TextView android:id="@+id/tv_price" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_marginLeft="10dp" android:gravity="center" android:text="合计:¥0.00" android:textColor="#ff00" android:layout_toRightOf="@id/checkbox2" /> <LinearLayout android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_alignParentRight="true" android:background="#ff0000"> <TextView android:id="@+id/tv_num" android:layout_width="100dp" android:layout_height="match_parent" android:background="#ff0000" android:gravity="center" android:text="结算(0)" android:textColor="#ffffff" android:textSize="15sp" /> </LinearLayout> </RelativeLayout> </RelativeLayout> 接下来创建第一级的.xml,取名 :item_parent_market.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="80dp" android:gravity="center_vertical" android:orientation="horizontal" > <CheckBox android:id="@+id/cb_parent" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="10dp" android:focusable="false" android:layout_marginBottom="10dp" android:layout_marginLeft="20dp"/> <TextView android:id="@+id/tv_number" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="20dp" android:text="12345678"/> </LinearLayout> 最后创建第二级的xml,取名 :item_child_market.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="match_parent" android:gravity="center_vertical" android:orientation="horizontal" > <CheckBox android:id="@+id/cb_child" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginBottom="30dp" android:layout_marginLeft="40dp" android:layout_marginTop="30dp" android:focusable="false" /> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical"> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal"> <TextView android:id="@+id/tv_content" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="20dp" android:text="什么手机" /> <TextView android:id="@+id/tv_pri" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="20dp" android:text="¥3000.00" android:textColor="#ff00" /> </LinearLayout> <TextView android:id="@+id/tv_time" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="20dp" android:text="2016-12-10" /> <TextView android:id="@+id/tv_msg" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="20dp" android:text="购买渠道:大陆国行" /> </LinearLayout> </LinearLayout>
二级列表我是自定义的,下面直接上代码:import android.content.Context; import android.util.AttributeSet; import android.widget.ExpandableListView; /** * 自定义二级列表 * Created by forever on 2017/9/6. */ public class CustomExpandableListView extends ExpandableListView { public CustomExpandableListView(Context context, AttributeSet attrs) { super(context, attrs); // TODO Auto-generated constructor stub } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { // TODO Auto-generated method stub int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST); super.onMeasure(widthMeasureSpec, expandSpec); } } 接下来就是创建的网络请求所需要的实体类,也就是bean对象,根据自己的需求创建:import java.util.List; /** * 1. 类的用途 实体类 * 2. @author forever * 3. @date 2017/9/6 17:10 */ public class PhonesInfo { public String flag; public String code; public List<DataInfo> data; public String getFlag() { return flag; } public void setFlag(String flag) { this.flag = flag; } public String getCode() { return code; } public void setCode(String code) { this.code = code; } public List<DataInfo> getData() { return data; } public void setData(List<DataInfo> data) { this.data = data; } public static class DataInfo { public String title; public List<DatasInfo> datas; public boolean allCheck = false; public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public List<DatasInfo> getDatas() { return datas; } public void setDatas(List<DatasInfo> datas) { this.datas = datas; } public boolean isAllCheck() { return allCheck; } public void setAllCheck(boolean allCheck) { this.allCheck = allCheck; } public static class DatasInfo { public int price; public String type_name; public String msg; public String add_time; public boolean itemCheck = false; public int getPrice() { return price; } public void setPrice(int price) { this.price = price; } public String getType_name() { return type_name; } public void setType_name(String type_name) { this.type_name = type_name; } public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } public String getAdd_time() { return add_time; } public void setAdd_time(String add_time) { this.add_time = add_time; } public boolean isItemCheck() { return itemCheck; } public void setItemCheck(boolean itemCheck) { this.itemCheck = itemCheck; } } } }
最后是MainActivity里的逻辑了:import android.database.DataSetObserver; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.support.v7.app.AppCompatActivity; import android.util.Log; import android.view.View; import android.view.ViewGroup; import android.widget.CheckBox; import android.widget.ExpandableListAdapter; import android.widget.TextView; import com.google.gson.Gson; import com.weiyuhui.ShoppingCart_01.R; import com.weiyuhui.ShoppingCart_01.bean.PhonesInfo; import com.weiyuhui.ShoppingCart_01.utils.OkHttp3Utils; import com.weiyuhui.ShoppingCart_01.view.CustomExpandableListView; import java.io.IOException; import java.util.List; import okhttp3.Call; import okhttp3.Callback; import okhttp3.Response; public class MainActivity extends AppCompatActivity implements View.OnClickListener { private CustomExpandableListView celv; private CheckBox checkBox; private TextView tv_num; private TextView tv_price; private PhonesInfo phonesInfo; private PhoneAdapter adapter; private Handler handler = new Handler() { @Override public void handleMessage(Message msg) { super.handleMessage(msg); switch (msg.what) { case 1: String str = (String) msg.obj; Log.i("xxx", str.toString()); Gson gson = new Gson(); phonesInfo = gson.fromJson(str, PhonesInfo.class); //适配数据 adapter = new PhoneAdapter(); celv.setAdapter(adapter); int count = celv.getCount(); for (int i = 0; i < count; i++) { //展开 celv.expandGroup(i); } break; } } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //获取数据 getData(); //获取控件ID celv = (CustomExpandableListView) findViewById(R.id.celv); checkBox = (CheckBox) findViewById(R.id.checkbox2); tv_num = (TextView) findViewById(R.id.tv_num); tv_price = (TextView) findViewById(R.id.tv_price); //去掉箭头 celv.setGroupIndicator(null); //CheckBox点击事件 checkBox.setOnClickListener(this); } //获取数据 private void getData() { String url = "http://result.eolinker.com/iYXEPGn4e9c6dafce6e5cdd23287d2bb136ee7e9194d3e9?uri=evaluation"; OkHttp3Utils.doGet(url, new Callback() { @Override public void onFailure(Call call, IOException e) { } @Override public void onResponse(Call call, Response response) throws IOException { String string = response.body().string(); Log.i("xxx", string.toString()); Message message = handler.obtainMessage(1, string); message.sendToTarget(); } }); } //全选的监听 @Override public void onClick(View v) { if (((CheckBox) v).isChecked()) { List<PhonesInfo.DataInfo> data = phonesInfo.getData(); for (int i = 0; i < data.size(); i++) { Log.i("xxx", data.get(i).isAllCheck() + ""); PhonesInfo.DataInfo groupDatas = phonesInfo.getData().get(i); groupDatas.setAllCheck(true); List<PhonesInfo.DataInfo.DatasInfo> datas = data.get(i).getDatas(); for (int j = 0; j < datas.size(); j++) { Log.i("xxx", datas.get(j).isItemCheck() + ""); List<PhonesInfo.DataInfo.DatasInfo> childDatas = groupDatas.getDatas(); for (PhonesInfo.DataInfo.DatasInfo childData : childDatas) { childData.setItemCheck(true); } } } //刷新界面 notifyCheckAdapter(); } else { List<PhonesInfo.DataInfo> data = phonesInfo.getData(); for (int i = 0; i < data.size(); i++) { Log.i("xxx", data.get(i).isAllCheck() + ""); PhonesInfo.DataInfo groupDatas = phonesInfo.getData().get(i); groupDatas.setAllCheck(false); List<PhonesInfo.DataInfo.DatasInfo> datas = data.get(i).getDatas(); for (int j = 0; j < datas.size(); j++) { Log.i("xxx", datas.get(j).isItemCheck() + ""); List<PhonesInfo.DataInfo.DatasInfo> childDatas = groupDatas.getDatas(); for (PhonesInfo.DataInfo.DatasInfo childData : childDatas) { childData.setItemCheck(false); } } } //刷新界面 notifyCheckAdapter(); } } @Override public void onPointerCaptureChanged(boolean hasCapture) { } //适配器 private class PhoneAdapter implements ExpandableListAdapter { @Override public void registerDataSetObserver(DataSetObserver observer) { } @Override public void unregisterDataSetObserver(DataSetObserver observer) { } @Override public int getGroupCount() { return phonesInfo.getData().size(); } @Override public int getChildrenCount(int groupPosition) { return phonesInfo.getData().get(groupPosition).getDatas().size(); } @Override public Object getGroup(int groupPosition) { return phonesInfo.getData().get(groupPosition); } @Override public Object getChild(int groupPosition, int childPosition) { return phonesInfo.getData().get(groupPosition).getDatas().get(childPosition); } @Override public long getGroupId(int groupPosition) { return groupPosition; } @Override public long getChildId(int groupPosition, int childPosition) { return childPosition; } @Override public boolean hasStableIds() { return false; } //一级 @Override public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) { View view = View.inflate(MainActivity.this, R.layout.item_parent_market, null); CheckBox cb_parent = (CheckBox) view.findViewById(R.id.cb_parent); TextView tv_number = (TextView) view.findViewById(R.id.tv_number); tv_number.setText(phonesInfo.getData().get(groupPosition).getTitle()); if (phonesInfo.getData().get(groupPosition).isAllCheck()) { cb_parent.setChecked(true); } else { cb_parent.setChecked(false); } //一级监听 cb_parent.setOnClickListener(new OnGroupClickListener(groupPosition, cb_parent)); return view; } //二级 @Override public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) { View view = View.inflate(MainActivity.this, R.layout.item_child_market, null); TextView tv_content = (TextView) view.findViewById(R.id.tv_content); TextView tv_time = (TextView) view.findViewById(R.id.tv_time); TextView tv_pri = (TextView) view.findViewById(R.id.tv_pri); TextView tv_msg = (TextView) view.findViewById(R.id.tv_msg); CheckBox cb_child = (CheckBox) view.findViewById(R.id.cb_child); tv_pri.setText("¥"+phonesInfo.getData().get(groupPosition).getDatas().get(childPosition).getPrice()); tv_content.setText(phonesInfo.getData().get(groupPosition).getDatas().get(childPosition).getType_name()); tv_time.setText(phonesInfo.getData().get(groupPosition).getDatas().get(childPosition).getAdd_time()); tv_msg.setText(phonesInfo.getData().get(groupPosition).getDatas().get(childPosition).getMsg()); if (phonesInfo.getData().get(groupPosition).getDatas().get(childPosition).isItemCheck()) { cb_child.setChecked(true); } else { cb_child.setChecked(false); } cb_child.setOnClickListener(new OnChildCheckListener(groupPosition, childPosition, cb_child)); return view; } @Override public boolean isChildSelectable(int groupPosition, int childPosition) { return true; } @Override public boolean areAllItemsEnabled() { return false; } @Override public boolean isEmpty() { return false; } @Override public void onGroupExpanded(int groupPosition) { } @Override public void onGroupCollapsed(int groupPosition) { } @Override public long getCombinedChildId(long groupId, long childId) { return 0; } @Override public long getCombinedGroupId(long groupId) { return 0; } } //一级监听 private class OnGroupClickListener implements View.OnClickListener { int groupPosition; CheckBox cb_parent; public OnGroupClickListener(int groupPosition, CheckBox cb_parent) { this.cb_parent = cb_parent; this.groupPosition = groupPosition; } @Override public void onClick(View v) { if (((CheckBox) v).isChecked()) { //一级全选 setCheck(true); } else { //取消全选 setCheck(false); checkBox.setChecked(false); } notifyCheckAdapter(); } public void setCheck(boolean checkFlag) { PhonesInfo.DataInfo groupDatas = phonesInfo.getData().get(groupPosition); List<PhonesInfo.DataInfo> data = phonesInfo.getData(); //一级状态 groupDatas.setAllCheck(checkFlag); //全选状态判断 int num = 0; for (int i = 0; i < data.size(); i++) { boolean allCheck = data.get(i).isAllCheck(); if (!allCheck) { num++; } } if (num == 0) { checkBox.setChecked(true); } else { checkBox.setChecked(false); } //二级状态 List<PhonesInfo.DataInfo.DatasInfo> childDatas = groupDatas.getDatas(); for (PhonesInfo.DataInfo.DatasInfo childData : childDatas) { //二级状态 childData.setItemCheck(checkFlag); } } } //二级监听 private class OnChildCheckListener implements View.OnClickListener { int groupPosition; int childPosition; CheckBox cb_child; public OnChildCheckListener(int groupPosition, int childPosition, CheckBox cb_child) { this.cb_child = cb_child; this.groupPosition = groupPosition; this.childPosition = childPosition; } @Override public void onClick(View v) { if (((CheckBox) v).isChecked()) { //子选中 phonesInfo.getData().get(groupPosition).getDatas().get(childPosition).setItemCheck(true); } else { //子未选中 phonesInfo.getData().get(groupPosition).getDatas().get(childPosition).setItemCheck(false); } //二级联动一级状态 setParentCheckFlag(); //检测状态 二级联动全选 int num = 0; for (int i = 0; i < phonesInfo.getData().size(); i++) { boolean allCheck = phonesInfo.getData().get(i).isAllCheck(); if (!allCheck) { num++; } } if (num == 0) { checkBox.setChecked(true); } else { checkBox.setChecked(false); } } //二级联动一级状态 private void setParentCheckFlag() { PhonesInfo.DataInfo dataInfo = phonesInfo.getData().get(groupPosition); List<PhonesInfo.DataInfo.DatasInfo> datasInfos = dataInfo.getDatas(); for (int i = 0; i < datasInfos.size(); i++) { if (!datasInfos.get(i).isItemCheck()) { //子未选中 父取消选中 dataInfo.setAllCheck(false); notifyCheckAdapter(); return; } if (i == datasInfos.size() - 1) { //子选中 父选中 dataInfo.setAllCheck(true); notifyCheckAdapter(); return; } } //没出现全选或者取消全选的时候执行的 sum(); } } //统计数量和价格 private void sum() { int num = 0; int price = 0; List<PhonesInfo.DataInfo> data = phonesInfo.getData(); for (PhonesInfo.DataInfo parentData : data) { for (PhonesInfo.DataInfo.DatasInfo child : parentData.getDatas()) { if (child.isItemCheck()) { num++; price += child.getPrice(); } } } tv_num.setText("结算(" + num + ")"); tv_price.setText("¥" + price); } //刷新适配器界面 private void notifyCheckAdapter() { sum(); celv.setAdapter(adapter); int count = celv.getCount(); for (int i = 0; i < count; i++) { celv.expandGroup(i); } } }
这就是二级购物车的实现逻辑了,欢迎大家指导!