京东购物车二级列表显示
接口有点多不过别慌让秀给你解说一下(接口都在适配器里,都是让Mianactivity调用的,别忘写权限)
先看下效果
先看主布局(二级列表的控件不用加依赖,然后几个TextView)
<?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/exlistview"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"></ExpandableListView>
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<CheckBox
android:id="@+id/quanxuan"
android:layout_weight="1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="全选"/>
<TextView
android:id="@+id/jiage"
android:layout_weight="1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="价格"/>
<TextView
android:id="@+id/jiesuan"
android:layout_weight="1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="去结算(0)"/>
</LinearLayout>
</LinearLayout>
MainActivity
package com.example.bwie.gowuche_1;
import android.annotation.SuppressLint;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.CheckBox;
import android.widget.ExpandableListView;
import android.widget.TextView;
import com.example.bwie.gowuche_1.adapter.Myadapter;
import com.example.bwie.gowuche_1.bean.MyBean;
import com.google.gson.Gson;
import java.io.IOException;
import java.util.ArrayList;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
public class MainActivity extends AppCompatActivity {
private ExpandableListView exlistview;
private CheckBox quanxuan;
private TextView jiage;
private TextView jiesuan;
private String mUrl="http://www.wanandroid.com/tools/mockapi/6523/restaurant-list";
private Myadapter adapter;
private ArrayList<MyBean.DataBean> list=new ArrayList<>();
@SuppressLint("HandlerLeak")
private Handler handler=new Handler(){
@Override
public void handleMessage(Message msg) {
String s= (String) msg.obj;
Gson gson=new Gson();
MyBean myBean = gson.fromJson(s, MyBean.class);
list.addAll(myBean.getData());
adapter.notifyDataSetChanged();
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
adapter = new Myadapter(list,this);
exlistview.setAdapter(adapter);
getData();
exlistview.setGroupIndicator(null);
adapter.setCallBack(new Myadapter.AdapterCallBack() {
@Override
public void setGroupCheck(int groupPosition) {
boolean childAllChecked = adapter.isChildAllChecked(groupPosition);
adapter.childAllChecked(groupPosition,!childAllChecked);
adapter.notifyDataSetChanged();
flushBottomLayout();
}
@Override
public void setChildCheck(int groupPosition, int childPosition) {
boolean childChecked = adapter.isChildChecked(groupPosition, childPosition);
adapter.setChildChecked(groupPosition,childPosition,!childChecked);
adapter.notifyDataSetChanged();
flushBottomLayout();
}
@Override
public void setNumber(int groupPosition, int childPosition, int number) {
adapter.setShangPingNumber(groupPosition,childPosition,number);
adapter.notifyDataSetChanged();
flushBottomLayout();
}
});
quanxuan.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
boolean allGoods = adapter.isAllGoods();
adapter.setAllGoodsisChecked(!allGoods);
adapter.notifyDataSetChanged();
flushBottomLayout();
}
});
}
private void getData() {
OkHttpClient okHttpClient=new OkHttpClient();
Request request=new Request.Builder().url(mUrl).build();
okHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) throws IOException {
handler.sendMessage(handler.obtainMessage(0,response.body().string()));
}
});
}
private void initView() {
exlistview = (ExpandableListView) findViewById(R.id.exlistview);
quanxuan = (CheckBox) findViewById(R.id.quanxuan);
jiage = (TextView) findViewById(R.id.jiage);
jiesuan = (TextView) findViewById(R.id.jiesuan);
}
public void flushBottomLayout(){
boolean allGoods = adapter.isAllGoods();
quanxuan.setChecked(allGoods);
int i = adapter.setAllNumber();
float v = adapter.setAllPrice();
jiage.setText("价格是:"+v);
jiesuan.setText("去结算+("+i+")");
}
}
一个二级列表的适配器
package com.example.bwie.gowuche_1.adapter;
import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseExpandableListAdapter;
import android.widget.CheckBox;
import android.widget.ExpandableListView;
import android.widget.ImageView;
import android.widget.TextView;
import com.bumptech.glide.Glide;
import com.example.bwie.gowuche_1.R;
import com.example.bwie.gowuche_1.bean.MyBean;
import com.example.bwie.gowuche_1.view.JiajianView;
import java.util.ArrayList;
import java.util.List;
public class Myadapter extends BaseExpandableListAdapter {
private ArrayList<MyBean.DataBean> list;
private Context context;
public Myadapter(ArrayList<MyBean.DataBean> list, Context context) {
this.list = list;
this.context = context;
}
@Override
public int getGroupCount() {
return list.size();
}
@Override
public int getChildrenCount(int groupPosition) {
return list.get(groupPosition).getSpus().size();
}
@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;
}
@Override
public View getGroupView(final int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
GroupHolder groupHolder=null;
if (convertView==null){
groupHolder=new GroupHolder();
convertView=View.inflate(context,R.layout.group_list,null);
groupHolder.Group_CB=convertView.findViewById(R.id.Group_CB);
groupHolder.Group_Name=convertView.findViewById(R.id.Group_Name);
convertView.setTag(groupHolder);
} else {
groupHolder = (GroupHolder) convertView.getTag();
}
groupHolder.Group_CB.setChecked(list.get(groupPosition).isGroupChecked());
groupHolder.Group_Name.setText(list.get(groupPosition).getName()+"");
//查看方法里组员的选中状态,并设置控件的选中的状态
groupHolder.Group_CB.setChecked(isChildAllChecked(groupPosition));
///接口回调点击父条目的事件
groupHolder.Group_CB.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (adapterCallBack!=null){
adapterCallBack.setGroupCheck(groupPosition);
}
}
});
return convertView;
}
@Override
public View getChildView(final int groupPosition, final int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
ClildHolder clildHolder=null;
if (convertView==null){
clildHolder=new ClildHolder();
convertView=View.inflate(context,R.layout.child_item,null);
clildHolder.Child_Check_CB=convertView.findViewById(R.id.Child_Check_CB);
clildHolder.Child_title=convertView.findViewById(R.id.Child_title);
clildHolder.Child_Icon=convertView.findViewById(R.id.Child_Icon);
clildHolder.Child_price=convertView.findViewById(R.id.Child_price);
clildHolder.jiajianView=convertView.findViewById(R.id.Jia_Jian_View);
convertView.setTag(clildHolder);
}else{
clildHolder= (ClildHolder) convertView.getTag();
}
clildHolder.Child_Check_CB.setChecked(list.get(groupPosition).getSpus().get(childPosition).isChildChecked());
clildHolder.Child_title.setText(list.get(groupPosition).getSpus().get(childPosition).getName());
clildHolder.Child_price.setText(list.get(groupPosition).getSpus().get(childPosition).getSkus().get(0).getPrice());
Glide.with(context).load(list.get(groupPosition).getSpus().get(childPosition).getPic_url()).into(clildHolder.Child_Icon);
//从自定的布局类里调用的方法赋值自己集合里的数量
clildHolder.jiajianView.setNumber(list.get(groupPosition).getSpus().get(childPosition).getPraise_num());
//接口回调点击子条目的事件
clildHolder.Child_Check_CB.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (adapterCallBack!=null){
//把组员的点击事件调回
adapterCallBack.setChildCheck(groupPosition,childPosition);
}
}
});
//接口回调点击加减的事件
clildHolder.jiajianView.setOnCountChange(new JiajianView.OnCountChange() {
@Override
public void setCount(int count) {
if (adapterCallBack!=null){
adapterCallBack.setNumber(groupPosition,childPosition,count);
}
}
});
return convertView;
}
@Override
public boolean isChildSelectable(int groupPosition, int childPosition) {
return false;
}
/*
* 这是二级列表的两个优化
* */
class GroupHolder{
CheckBox Group_CB;
TextView Group_Name;
}
class ClildHolder{
CheckBox Child_Check_CB;
TextView Child_title,Child_price;
ImageView Child_Icon;
JiajianView jiajianView;
}
/**
*接下来首先考虑一个小组的选中我们可以想象一下
* 1.比如组长说今天晚上敲技能,我们必须都得做完(组长肯定是选中的状态),这就是组长选中组员也要跟着选中
* 2.再比如说组长说今天晚上随便敲不检查(组长肯定是不选的状态),那我们组员可以做也可以不做(也就是可选可不选)
* 3.就是说当组员全部做完的时候组长是不是也得做完,身为一个组长要以身作责,
* 所以说当组员全部选中的时候,组长也是选中的状态
*/
//一、点击组长组员全选上(参数1.组长的下标,2.状态)
public void childAllChecked(int groupPosition,boolean isCheck){
List<MyBean.DataBean.SpusBean> spus = list.get(groupPosition).getSpus();
for (int i = 0; i <spus.size() ; i++) {
MyBean.DataBean.SpusBean spusBean = spus.get(i);
spusBean.setChildChecked(isCheck);
}
}
//判断小组是否全被选中
public boolean isChildAllChecked(int groupPosition){
boolean boo=true;
List<MyBean.DataBean.SpusBean> spus = list.get(groupPosition).getSpus();
for (int i = 0; i <spus.size() ; i++) {
MyBean.DataBean.SpusBean spusBean = spus.get(i);
if (!spusBean.isChildChecked()){
//只要有一个没选中就返回false
// !就是不是选中的状态
return false;
}
}
return boo;
}
//二、
//给组员进行赋值让你点的条目选中
public void setChildChecked(int groupPositon, int childPositon, boolean isCheckBox){
MyBean.DataBean.SpusBean spusBean = list.get(groupPositon).getSpus().get(childPositon);
spusBean.setChildChecked(isCheckBox);
}
//查看当前这个组员有没有被选中(做完作业)
public boolean isChildChecked(int groupPosition,int childPosition){
MyBean.DataBean.SpusBean spusBean = list.get(groupPosition).getSpus().get(childPosition);
if (spusBean.isChildChecked()){
return true;
}
return false;
}
/*
*选中下面的number++
* */
//写方法让
public void setShangPingNumber(int groupPositon, int childPositon,int number){
MyBean.DataBean.SpusBean spusBean = list.get(groupPositon).getSpus().get(childPositon);
spusBean.setPraise_num(number);
}
//判断商品是全部选中,选中为true不选中为false
public boolean isAllGoods(){
boolean boo=true;
for (int i = 0; i <list.size() ; i++) {
List<MyBean.DataBean.SpusBean> spus = list.get(i).getSpus();
for (int j = 0; j <spus.size() ; j++) {
MyBean.DataBean.SpusBean spusBean = spus.get(j);
if (!spusBean.isChildChecked()){
boo=false;
}
}
}
return boo;
}
//全选和反选
public void setAllGoodsisChecked(boolean isAllChecked){
for (int i = 0; i <list.size() ; i++) {
List<MyBean.DataBean.SpusBean> spus = list.get(i).getSpus();
for (int j = 0; j <spus.size() ; j++) {
MyBean.DataBean.SpusBean spusBean = spus.get(j);
spusBean.setChildChecked(isAllChecked);
}
}
}
//既然全选那必然要把数量传到主页面
public int setAllNumber(){
int number=0;
for (int i = 0; i <list.size() ; i++) {
List<MyBean.DataBean.SpusBean> spus = list.get(i).getSpus();
for (int j = 0; j <spus.size() ; j++) {
MyBean.DataBean.SpusBean spusBean = spus.get(j);
if (spusBean.isChildChecked()){
number+=spusBean.getPraise_num();
}
}
}
return number;
}
//还有全部商品的价格
public float setAllPrice(){
float allprice=0;
for (int i = 0; i <list.size(); i++) {
List<MyBean.DataBean.SpusBean> spus = list.get(i).getSpus();
for (int j = 0; j <spus.size(); j++) {
MyBean.DataBean.SpusBean spusBean = spus.get(j);
if (spusBean.isChildChecked()){
allprice= allprice+spusBean.getPraise_num()*Float.parseFloat(spusBean.getSkus().get(0).getPrice());
}
}
}
return allprice;
}
/**
*接口回调三部曲
*/
public interface AdapterCallBack{
//第一个方法是判断大的列表的选中状态
void setGroupCheck(int groupPosition);
//第二个方法是判断小的列表的选中状态
void setChildCheck(int groupPosition,int childPosition);
//第二个方法是判断自定义view的加减刷新状态
void setNumber(int groupPosition,int childPosition,int number);
}
private AdapterCallBack adapterCallBack;
public void setCallBack(AdapterCallBack adapterCallBack){
this.adapterCallBack=adapterCallBack;
}
}
然后二级列表的一级显示布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal" android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- focusable设置不强焦点 -->
<CheckBox
android:id="@+id/Group_CB"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:focusable="false"/>
<TextView
android:id="@+id/Group_Name"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
然后二级列表的二级显示布局(里边有一个自定义view)
<?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:orientation="horizontal">
<CheckBox
android:id="@+id/Child_Check_CB"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<ImageView
android:id="@+id/Child_Icon"
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:layout_weight="1"
android:orientation="vertical">
<TextView
android:id="@+id/Child_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxLines="2"
android:text="商品标题" />
<TextView
android:id="@+id/Child_price"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:text="¥0.0" />
</LinearLayout>
<com.example.bwie.gowuche_1.view.JiajianView
android:id="@+id/Jia_Jian_View"
android:layout_width="wrap_content"
android:layout_height="wrap_content"></com.example.bwie.gowuche_1.view.JiajianView>
</LinearLayout>
自定义view的布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="30dp"
android:layout_gravity="center_vertical"
android:layout_marginLeft="10dp"
android:background="#99000000"
android:gravity="center_vertical"
android:padding="2dp">
<TextView
android:id="@+id/delete_tv"
android:layout_width="25dp"
android:layout_height="match_parent"
android:background="#ffffff"
android:gravity="center"
android:text="-"
android:textSize="16sp" />
<TextView
android:id="@+id/product_number_tv"
android:layout_width="25dp"
android:layout_height="match_parent"
android:layout_marginLeft="2dp"
android:layout_weight="1"
android:background="#ffffff"
android:gravity="center"
android:text="1" />
<TextView
android:id="@+id/add_tv"
android:layout_width="25dp"
android:layout_height="match_parent"
android:layout_marginLeft="2dp"
android:background="#ffffff"
android:gravity="center"
android:text="+"
android:textSize="16sp" />
</LinearLayout>
自定义view类
package com.example.bwie.gowuche_1.view;
import android.content.Context;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import com.example.bwie.gowuche_1.R;
public class JiajianView extends LinearLayout implements View.OnClickListener {
private TextView delete_tv;
private TextView product_number_tv;
private TextView add_tv;
private int count;
public JiajianView(Context context,AttributeSet attrs) {
super(context, attrs);
LayoutInflater.from(context).inflate(R.layout.add_remove_view_layout, this);
initView();
}
private void initView() {
delete_tv=findViewById(R.id.delete_tv);
add_tv=findViewById(R.id.add_tv);
product_number_tv=findViewById(R.id.product_number_tv);
delete_tv.setOnClickListener(this);
add_tv.setOnClickListener(this);
}
public void setNumber(int number){
this.count=number;
product_number_tv.setText(count+"");
}
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.add_tv:
count++;
product_number_tv.setText(count+"");
if (onCountChange!=null){
onCountChange.setCount(count);
}
break;
case R.id.delete_tv:
if (count>0){
count--;
product_number_tv.setText(count+"");
if (onCountChange!=null){
onCountChange.setCount(count);
}
}else{
Toast.makeText(getContext(), "商品已售空", Toast.LENGTH_SHORT).show();
}
break;
}
}
public interface OnCountChange{
void setCount(int count);
}
private OnCountChange onCountChange;
public void setOnCountChange(OnCountChange onCountChange){
this.onCountChange=onCountChange;
}
}