首先看个效果图:
在我们做这个是时候,首先必须一定要导入权限:
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <!-- 网络状态 --> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
然后是导入依赖
之后就是看我们的代码了:
因为购物车上半部分是我们的商品,我们借助ExpanableListView,下半部分则是推荐的商品,使用LinearLayout,
所以说我们要借助ScrollView来实现滑动,而这时候就会出现滑动冲突,所以需要自定义ExpanableListView,
在onMeasure方法中写入int height = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);super.onMeasure(widthMeasureSpec, height); 来解决滑动冲突。
那么看下我们的主页面布局吧:<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <ScrollView android:layout_width="match_parent" android:layout_height="match_parent" android:layout_weight="1"> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <com.bwie.project.cart.expanlistview.CartExpanableListview android:id="@+id/expand_lv" android:layout_width="match_parent" android:layout_height="wrap_content"> </com.bwie.project.cart.expanlistview.CartExpanableListview> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:background="#00ff00" android:orientation="vertical"> </LinearLayout> </LinearLayout> </ScrollView> <LinearLayout android:id="@+id/linear_layout" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_alignParentBottom="true" android:layout_weight="9" android:gravity="bottom" android:orientation="horizontal"> <CheckBox android:id="@+id/check_all" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="10dp" android:background="@drawable/check_box_selector" android:button="@null" /> <TextView android:id="@+id/text_total" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="2" android:text="合计:¥0.00" /> <TextView android:id="@+id/text_buy" android:layout_width="0dp" android:layout_height="50dp" android:layout_weight="1" android:background="#ff0000" android:gravity="center" android:text="去结算(0)" android:textColor="#ffffff" /> </LinearLayout> </LinearLayout>在看下我们一级列表的布局:<?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" android:padding="10dp"> <CheckBox android:id="@+id/check_group" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/check_box_selector" android:button="@null" /> <TextView android:id="@+id/text_group" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="10dp" android:text="京东自营" /> </LinearLayout>然后就是二级列表的布局:<?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:padding="10dp"> <CheckBox android:id="@+id/check_child" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerVertical="true" android:background="@drawable/check_box_selector" android:button="@null" /> <ImageView android:id="@+id/image_good" android:layout_width="80dp" android:layout_height="80dp" android:layout_centerVertical="true" android:layout_marginLeft="10dp" android:layout_toRightOf="@+id/check_child" /> <TextView android:id="@+id/text_title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignTop="@+id/image_good" android:layout_marginLeft="10dp" android:layout_toRightOf="@+id/image_good" android:maxLines="2" android:minLines="2" /> <TextView android:id="@+id/text_price" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignBottom="@+id/image_good" android:layout_marginLeft="10dp" android:layout_toRightOf="@+id/image_good" android:text="¥99.99" android:textColor="#ff0000" /> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignBottom="@+id/image_good" android:layout_alignParentRight="true" android:orientation="horizontal"> <TextView android:id="@+id/text_jian" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/bian_kuang_line" android:padding="5dp" android:text="一" /> <TextView android:id="@+id/text_num" android:layout_width="wrap_content" android:layout_height="match_parent" android:background="@drawable/bian_kuang_line" android:gravity="center" android:paddingBottom="5dp" android:paddingLeft="10dp" android:paddingRight="10dp" /> <TextView android:id="@+id/text_add" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/bian_kuang_line" android:padding="5dp" android:text="十" /> </LinearLayout> </RelativeLayout>之后就开始我们的逻辑代码了:先看下我们的bean类吧:
第一个就是接口的bean类了,有点多久不写了,
第二个就是一个自定义的bean类,包括选择的数量及最后的总价:
public class CountPriceBean { private Double price; private int count; public CountPriceBean(Double price, int count) { this.price = price; this.count = count; } public Double getPrice() { return price; } public void setPrice(Double price) { this.price = price; } public int getCount() { return count; } public void setCount(int count) { this.count = count; } }然后就是我们的适配器了:package com.bwie.project.cart.adapter; import android.content.Context; import android.os.Handler; import android.os.Message; import android.util.Log; 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.bumptech.glide.Glide; import com.bwie.project.R; import com.bwie.project.cart.bean.CartBean; import com.bwie.project.cart.bean.CountPriceBean; import java.util.List; public class MyExpanAdapter extends BaseExpandableListAdapter { private List<CartBean.DataBean> listGroup; private List<List<CartBean.DataBean.ListBean>> listChilds; private Context context; private Handler handler; public MyExpanAdapter(List<CartBean.DataBean> listGroup, List<List<CartBean.DataBean.ListBean>> listChild, Context context, Handler handler) { this.listGroup = listGroup; this.listChilds = listChild; this.context = context; this.handler = handler; } @Override public int getGroupCount() { return listGroup.size(); } @Override public int getChildrenCount(int groupPosition) { return listChilds.get(groupPosition).size(); } @Override public Object getGroup(int groupPosition) { return listGroup.get(groupPosition); } @Override public Object getChild(int groupPosition, int childPosition) { return listChilds.get(groupPosition).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 true; } @Override public View getGroupView(final int groupPosition, boolean isExpanded, View view, ViewGroup parent) { final GroupHolder holder; if (view == null) { holder = new GroupHolder(); view = View.inflate(context, R.layout.group_item, null); holder.check_group = view.findViewById(R.id.check_group); holder.text_group = view.findViewById(R.id.text_group); view.setTag(holder); } else { holder = (GroupHolder) view.getTag(); } final CartBean.DataBean dataBean = listGroup.get(groupPosition); holder.text_group.setText(dataBean.getSellerName()); holder.check_group.setChecked(dataBean.isGroupChecked()); holder.check_group.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Log.e("TAG", "ASS"); dataBean.setGroupChecked(!dataBean.isGroupChecked()); //根据当前一级列表的状态,改变改组里面二级列表的状态 changeChildState(groupPosition, dataBean.isGroupChecked()); //判断一级商家是否全部选中,来决定下面全选是否选中 changeAllState(isAllGroupChecked()); //发送数量和价格 sendPriceAndCount(); //刷新适配器 notifyDataSetChanged(); } }); return view; } /* * 设置二级的状态 * */ private void changeChildState(int groupPosition, boolean groupChecked) { List<CartBean.DataBean.ListBean> listBeen = listChilds.get(groupPosition); for (int i = 0; i < listBeen.size(); i++) { listBeen.get(i).setSelected(groupChecked ? "1" : "0"); } } /* * 设置下面的全选的状态 * */ private boolean isAllGroupChecked() { for (int i = 0; i < listGroup.size(); i++) { if (!listGroup.get(i).isGroupChecked()) { return false; } } return true; } /* * 根据一级列表是否全部选中,判断外面是否选中 * */ private void changeAllState(boolean allGroupChecked) { Message obtain = Message.obtain(); obtain.obj = allGroupChecked; obtain.what = 0; handler.sendMessage(obtain); } @Override public View getChildView(final int groupPosition, int childPosition, boolean isLastChild, View view, ViewGroup parent) { ChildHolder holder; if (view == null) { holder = new ChildHolder(); view = View.inflate(context, R.layout.child_item, null); holder.check_child = view.findViewById(R.id.check_child); holder.image_good = view.findViewById(R.id.image_good); holder.text_title = view.findViewById(R.id.text_title); holder.text_price = view.findViewById(R.id.text_price); holder.text_jian = view.findViewById(R.id.text_jian); holder.text_num = view.findViewById(R.id.text_num); holder.text_add = view.findViewById(R.id.text_add); view.setTag(holder); } else { holder = (ChildHolder) view.getTag(); } final CartBean.DataBean.ListBean listBean = listChilds.get(groupPosition).get(childPosition); holder.check_child.setChecked(listBean.getSelected().equals("0") ? false : true); holder.text_title.setText(listBean.getTitle()); Glide.with(context).load(listBean.getImages().split("!")[0]).into(holder.image_good); holder.text_price.setText(listBean.getPrice() + ""); holder.text_num.setText(listBean.getNum() + ""); holder.check_child.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { listBean.setSelected(listBean.getSelected().equals("0") ? "1" : "0"); //再次重新发送数量及价格 sendPriceAndCount(); //判断子条目是否选中 if (listBean.getSelected().equals("1")) { //判断二级列表是否全部选中 if (isAllChildChecked(groupPosition)) { //根据二级列表是否全选中,设置当前组一级列表 changeGroupState(groupPosition, true); //根据二级列表是否全选中,设置全选状态 changeAllState(isAllGroupChecked()); } } else { //如果有一个没选中,就需要改变当前组的状态 changeGroupState(groupPosition, false); //设置全选 changeAllState(isAllGroupChecked()); } notifyDataSetChanged(); } }); holder.text_jian.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (listBean.getNum() == 1) { return; } listBean.setNum(listBean.getNum() - 1); if (listBean.getSelected().equals("1")) { sendPriceAndCount(); } notifyDataSetChanged(); } }); holder.text_add.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { listBean.setNum(listBean.getNum() + 1); if (listBean.getSelected().equals("1")) { sendPriceAndCount(); } notifyDataSetChanged(); } }); return view; } private void changeGroupState(int groupPosition, boolean b) { listGroup.get(groupPosition).setGroupChecked(b); } private boolean isAllChildChecked(int groupPosition) { List<CartBean.DataBean.ListBean> listBeen = listChilds.get(groupPosition); for (int i = 0; i < listBeen.size(); i++) { CartBean.DataBean.ListBean listBean = listBeen.get(i); if (listBean.getSelected().equals("0")) { return false; } } return true; } @Override public boolean isChildSelectable(int groupPosition, int childPosition) { return true; } /* * 计算数量及价格 * */ private void sendPriceAndCount() { double price = 0; int count = 0; for (int i = 0; i < listGroup.size(); i++) { List<CartBean.DataBean.ListBean> list = listGroup.get(i).getList(); for (int j = 0; j < list.size(); j++) { CartBean.DataBean.ListBean listBean = list.get(j); if (listBean.getSelected().equals("1")) { count += listBean.getNum(); price += listBean.getNum() * listBean.getPrice(); } } } // for (int i = 0; i < listChilds.size(); i++) { // List<CartBean.DataBean.ListBean> listBeen = listChilds.get(i); // for (int j = 0; j < listBeen.size(); j++) { // CartBean.DataBean.ListBean listBean = listBeen.get(j); // if (listBean.getSelected() == 1) { // count += listBean.getNum(); // price += listBean.getNum() * listBean.getPrice(); // } // } // } CountPriceBean countPriceBean = new CountPriceBean(price, count); Message message = Message.obtain(); message.what = 1; message.obj = countPriceBean; handler.sendMessage(message); } /* * 设置是否全选 * */ public void setIfCheckAll(boolean b) { for (int i = 0; i < listGroup.size(); i++) { listGroup.get(i).setGroupChecked(b); List<CartBean.DataBean.ListBean> list = listGroup.get(i).getList(); for (int j = 0; j < list.size(); j++) { list.get(j).setSelected(b ? "1" : "0"); } } sendPriceAndCount(); notifyDataSetChanged(); } class GroupHolder { CheckBox check_group; TextView text_group; } class ChildHolder { CheckBox check_child; ImageView image_good; TextView text_title; TextView text_price; TextView text_jian; TextView text_num; TextView text_add; } }最后就是我们主页的逻辑代码了:package com.bwie.project.fragment; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.support.annotation.Nullable; import android.support.v4.app.Fragment; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.CheckBox; import android.widget.TextView; import android.widget.Toast; import com.bwie.project.R; import com.bwie.project.cart.adapter.MyExpanAdapter; import com.bwie.project.cart.bean.CartBean; import com.bwie.project.cart.bean.CountPriceBean; import com.bwie.project.cart.expanlistview.CartExpanableListview; import com.bwie.project.cart.presenter.ExpanPresenter; import com.bwie.project.cart.view.ExpanView; import java.util.ArrayList; import java.util.List; public class Fragment_Cart extends Fragment implements View.OnClickListener, ExpanView { private String uid; private CheckBox check_all; private TextView text_total; private TextView text_buy; private CartExpanableListview expand_lv; private ExpanPresenter expanPresenter; private MyExpanAdapter adapter; public String getUid() { return uid; } public void setUid(String uid) { this.uid = uid; } private Handler handler = new Handler() { @Override public void handleMessage(Message msg) { super.handleMessage(msg); int what = msg.what; if (what == 0) { boolean b = (boolean) msg.obj; check_all.setChecked(b); } if (what == 1) { CountPriceBean countPriceBean = (CountPriceBean) msg.obj; text_total.setText("合计:" + countPriceBean.getPrice()); text_buy.setText("去结算(" + countPriceBean.getCount() + ")"); } } }; @Nullable @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_cart, container, false); Log.e("TAG", getUid() + ""); check_all = view.findViewById(R.id.check_all); text_total = view.findViewById(R.id.text_total); text_buy = view.findViewById(R.id.text_buy); expand_lv = view.findViewById(R.id.expand_lv); //去掉默认的指示器 expand_lv.setGroupIndicator(null); expanPresenter = new ExpanPresenter(this); check_all.setOnClickListener(this); return view; } @Override public void onClick(View v) { switch (v.getId()) { case R.id.check_all: adapter.setIfCheckAll(check_all.isChecked()); break; } } @Override public void onResume() { super.onResume(); //MVP中请求数据 expanPresenter.getData(getUid()); Log.e("TAG", 1 + ""); } @Override public void onFailed() { Toast.makeText(getContext(), "请求数据失败,请重新请求!", Toast.LENGTH_SHORT).show(); } @Override public void onSuccess(CartBean cartBean) { List<CartBean.DataBean> listGroup = cartBean.getData(); List<List<CartBean.DataBean.ListBean>> listChilds = new ArrayList<>(); for (int i = 0; i < listGroup.size(); i++) { listChilds.add(listGroup.get(i).getList()); } //设置适配器 adapter = new MyExpanAdapter(listGroup, listChilds, getContext(), handler); expand_lv.setAdapter(adapter); for (int i = 0; i < listGroup.size(); i++) { expand_lv.expandGroup(i); } } }就这样,一个简单的二级列表购物车就OK了。