Android商城类app都会存在购物车页面,大部分的购物车中商品都是整体结算。本篇文章是介绍通过ExpandListView实现购物车页面,每个商家商品可单独进行结算。
如图:

整体结算只需要一个ListView或RecyclerView就可以实现,而单个商家结算如果使用一个RecyclerView来实现的话,
需要将服务端返回的数据转换成自己的格式,通常
服务端返回的json格式应该是数据是商家的数据,每个item再包括商品的list。
转换的话需要将商品list与商家list放在同一级,
这样实现商品全选单选也比较麻烦,所以
这里采取ExpandListView来实现。
activity_main中是普通ExpandableListView,设置不显示下拉图标shoppingCartListView.setGroupIndicator(null);
获取数据setAdapter
后将子item全部展开并设置parentItem
不能点击:
// 将子项全部展开for (int i = 0; i < list.size(); i++) {shoppingCartListView.expandGroup(i);}// 这是parent不能点击shoppingCartListView.setOnGroupClickListener(new ExpandableListView.OnGroupClickListener() {@Overridepublic boolean onGroupClick(ExpandableListView parent, View v, int groupPosition, long id) {return true;}});adapter中父item只显示:
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center_vertical"> <RelativeLayout android:layout_width="40dp" android:layout_height="40dp"> <CheckBox android:id="@+id/cb_shopping_cart_parent" android:layout_width="40dp" android:layout_height="40dp" /> </RelativeLayout> <TextView android:id="@+id/tv_merchant_name" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginLeft="50dp" android:layout_weight="1" android:drawablePadding="10dp" android:ellipsize="end" android:singleLine="true" tools:text="测试" /> <TextView android:id="@+id/tv_edit" android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center" android:padding="15dp" android:text="编辑" /> </LinearLayout></LinearLayout>shopping_cart_item.xml
子item中显示:
shopping_cart_child_item.xml:
<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <RelativeLayout android:id="@+id/ll_shopping_cart_child" android:layout_width="30dp" android:layout_height="80dp" android:layout_marginLeft="10dp" android:paddingTop="28dp"> <CheckBox android:id="@+id/cb_shopping_cart_child" android:layout_width="40dp" android:layout_height="40dp" android:layout_centerVertical="true" /> </RelativeLayout> <!-- 这里开始 --> <LinearLayout android:id="@+id/ll_shopping_cart_child_item_content" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginLeft="10dp" android:layout_toRightOf="@+id/ll_shopping_cart_child" android:orientation="vertical" android:paddingTop="2dp"> <RelativeLayout android:id="@+id/shopping_cart_child" android:layout_width="wrap_content" android:layout_height="0dp" android:layout_marginBottom="5dp" android:layout_weight="1"> <!-- 图 --> <RelativeLayout android:id="@+id/rl_shopping_cart" android:layout_width="80dp" android:layout_height="80dp" android:layout_marginLeft="2dp"> <ImageView android:id="@+id/iv_shopping_cart" android:layout_width="80dp" android:layout_height="80dp" android:scaleType="centerCrop" /> </RelativeLayout> <RelativeLayout android:layout_width="match_parent" android:layout_height="80dp" android:layout_marginLeft="10dp" android:layout_toRightOf="@+id/rl_shopping_cart"> <RelativeLayout android:id="@+id/rl_shopping_cart_not_edit" android:layout_width="match_parent" android:layout_height="80dp" android:layout_centerVertical="true" android:visibility="visible"> <TextView android:id="@+id/tv_child_item_goods_title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:layout_marginTop="10dp" android:ellipsize="end" android:lines="1" /> <TextView android:id="@+id/tv_shopping_cart_unit_PRice" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_marginBottom="10dp" tools:text="测试" /> <LinearLayout android:id="@+id/tv_child_item_goods_number" android:layout_width="wrap_content" android:layout_height="30dp" android:layout_alignParentBottom="true" android:layout_centerVertical="true" android:layout_marginLeft="20dp" android:layout_toRightOf="@+id/tv_shopping_cart_unit_price" android:orientation="horizontal"> <ImageButton android:id="@+id/tv_shopping_cart_sub" android:layout_width="25dp" android:layout_height="match_parent" android:background="#cccccc" android:src="@drawable/icon_shoppingcart_sub" /> <EditText android:id="@+id/et_shopping_cart_child_count" android:layout_width="50dp" android:layout_height="match_parent" android:clickable="false" android:background="@null" android:focusable="false" android:focusableInTouchMode="false" android:gravity="center" android:text="1" android:textSize="16sp" /> <ImageButton android:id="@+id/tv_shopping_cart_add" android:layout_width="25dp" android:layout_height="match_parent" android:background="#cccccc" android:src="@drawable/icon_shoppingcart_add" /> </LinearLayout> </RelativeLayout> <LinearLayout android:id="@+id/ll_shopping_cart_edit" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_alignParentLeft="true" android:layout_alignParentStart="true" android:layout_alignParentTop="true" android:visibility="gone"> <LinearLayout android:id="@+id/ll_edit_add_sub" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:gravity="center"> <TextView android:id="@+id/iv_shopping_cart_sub_edit" android:layout_width="wrap_content" android:layout_height="wrap_content" android:paddingLeft="20dp" android:paddingRight="20dp" android:text="—" android:textColor="#a9a9a9" android:textSize="28sp" /> <EditText android:id="@+id/et_shopping_cart_child_count_edit" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:background="@null" android:clickable="false" android:focusable="false" android:focusableInTouchMode="false" android:gravity="center" android:text="1" /> <TextView android:id="@+id/iv_shopping_cart_add_edit" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginRight="30dp" android:paddingLeft="20dp" android:paddingRight="20dp" android:text="+" android:textColor="#a9a9a9" android:textSize="34sp" /> </LinearLayout> <TextView android:id="@+id/tv_shopping_cart_delete_edit" android:layout_width="38dp" android:layout_height="match_parent" android:gravity="center" android:text="删除" /> </LinearLayout> </RelativeLayout> </RelativeLayout> </LinearLayout> <View android:id="@+id/view" android:layout_width="match_parent" android:layout_height="1dp" android:layout_below="@+id/ll_shopping_cart_child_item_content" android:layout_marginTop="12dp" /> <LinearLayout android:id="@+id/ll_shopping_cart_child_item_price" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@+id/view" android:orientation="vertical"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center_vertical" android:orientation="horizontal"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="30dp" android:text="合计:" /> <TextView android:id="@+id/tv_shopping_cart_price" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginLeft="15dp" android:layout_weight="1" tools:text="15" /> <TextView android:id="@+id/tv_confirm" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginBottom="20dp" android:layout_marginRight="20dp" android:layout_marginTop="20dp" android:background="@android:color/holo_red_dark" android:paddingBottom="20dp" android:paddingLeft="50dp" android:paddingRight="50dp" android:paddingTop="20dp" android:text="去结算" android:textColor="@android:color/white" /> </LinearLayout> <View android:layout_width="match_parent" android:layout_height="20dp" /> </LinearLayout></RelativeLayout>adapter的getChildView中控制是否显示结算部分:
if (childPosition == shoppingCartEntity.getGoodsInShoppingCarts().size() - 1) { childHolder.priceAndConfirView.setVisibility(View.VISIBLE); } else { childHolder.priceAndConfirView.setVisibility(View.GONE); }下面是adapter完整代码:
import android.content.Context;import android.text.TextUtils;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.BaseExpandableListAdapter;import android.widget.CheckBox;import android.widget.EditText;import android.widget.ImageView;import android.widget.TextView;import com.bumptech.glide.Glide;import com.bumptech.glide.load.engine.DiskCacheStrategy;import java.util.ArrayList;import java.util.List;/** * Created by cxn on 2017/2/25. */public class ShoppingCartAdapter extends BaseExpandableListAdapter { private Context context; private List<DataEntity.ShoppingCartEntity> shoppingCarts; public ShoppingCartAdapter(Context context, List<DataEntity.ShoppingCartEntity> shoppingCarts) { this.context = context; this.shoppingCarts = shoppingCarts; } @Override public int getGroupCount() { return shoppingCarts == null ? 0 : shoppingCarts.size(); } @Override public int getChildrenCount(int groupPosition) { return shoppingCarts.get(groupPosition) == null ? 0 : shoppingCarts.get(groupPosition).getGoodsInShoppingCarts().size(); } @Override public Object getGroup(int groupPosition) { return shoppingCarts.get(groupPosition); } @Override public Object getChild(int groupPosition, int childPosition) { return shoppingCarts.get(groupPosition).getGoodsInShoppingCarts().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(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) { final GroupHolder groupHolder; if (convertView == null) { groupHolder = new GroupHolder(); convertView = LayoutInflater.from(context).inflate(R.layout.shopping_cart_item, parent, false); groupHolder.shoppingCartParentCheckBox = (CheckBox) convertView.findViewById(R.id.cb_shopping_cart_parent); groupHolder.merchantNameTextView = (TextView) convertView.findViewById(R.id.tv_merchant_name); groupHolder.editView = (TextView) convertView.findViewById(R.id.tv_edit); convertView.setTag(groupHolder); } else { groupHolder = (GroupHolder) convertView.getTag(); } final DataEntity.ShoppingCartEntity shoppingCartEntity = shoppingCarts.get(groupPosition); groupHolder.shoppingCartParentCheckBox.setClickable(true); groupHolder.shoppingCartParentCheckBox.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { List<DataEntity.ShoppingCartEntity.GoodsInShoppingCartEntity> list = shoppingCartEntity.getGoodsInShoppingCarts(); boolean b = shoppingCartEntity.isCheck(); shoppingCartEntity.setCheck(!b); for (DataEntity.ShoppingCartEntity.GoodsInShoppingCartEntity g : list) { g.setIsCheck(!b); } notifyDataSetChanged(); } }); groupHolder.shoppingCartParentCheckBox.setChecked(shoppingCartEntity.isCheck()); final boolean isEdit = shoppingCartEntity.isEdit(); if (isEdit) { groupHolder.editView.setText("完成"); } else { groupHolder.editView.setText("编辑"); } groupHolder.editView.setClickable(true); groupHolder.editView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { shoppingCartEntity.setEdit(!isEdit); notifyDataSetChanged(); } }); groupHolder.merchantNameTextView.setText(shoppingCartEntity.getParentName()); return convertView; } @Override public View getChildView(int groupPosition, final int childPosition, boolean isLastChild, View convertView, ViewGroup parent) { final ChildHolder childHolder; if (convertView == null) { childHolder = new ChildHolder(); convertView = LayoutInflater.from(parent.getContext()).inflate(R.layout.shopping_cart_child_item, parent, false); childHolder.editView = convertView.findViewById(R.id.ll_shopping_cart_edit); childHolder.shoppingCartChildCheckBox = (CheckBox) convertView.findViewById(R.id.cb_shopping_cart_child); childHolder.addTextView = convertView.findViewById(R.id.tv_shopping_cart_add); childHolder.subTextView = convertView.findViewById(R.id.tv_shopping_cart_sub); childHolder.shoppingCartCountEditText = (EditText) convertView.findViewById(R.id.et_shopping_cart_child_count); childHolder.shoppingCartChildTitle = (TextView) convertView.findViewById(R.id.tv_child_item_goods_title); childHolder.shoppingCartUnitPrice = (TextView) convertView.findViewById(R.id.tv_shopping_cart_unit_price); childHolder.imageView = (ImageView) convertView.findViewById(R.id.iv_shopping_cart); childHolder.deleteView = convertView.findViewById(R.id.tv_shopping_cart_delete_edit); childHolder.editAddTextView = convertView.findViewById(R.id.iv_shopping_cart_add_edit); childHolder.editSubTextView = convertView.findViewById(R.id.iv_shopping_cart_sub_edit); childHolder.editShoppingCartCountEditText = (EditText) convertView.findViewById(R.id.et_shopping_cart_child_count_edit); childHolder.priceAndConfirView = convertView.findViewById(R.id.ll_shopping_cart_child_item_price); childHolder.shoppingCartPriceTextView = (TextView) convertView.findViewById(R.id.tv_shopping_cart_price); childHolder.confirmTextView = (TextView) convertView.findViewById(R.id.tv_confirm); childHolder.numberLayout = convertView.findViewById(R.id.tv_child_item_goods_number); childHolder.editAddSubView = convertView.findViewById(R.id.ll_edit_add_sub); convertView.setTag(childHolder); } else { childHolder = (ChildHolder) convertView.getTag(); } final DataEntity.ShoppingCartEntity shoppingCartEntity = shoppingCarts.get(groupPosition); final List<DataEntity.ShoppingCartEntity.GoodsInShoppingCartEntity> shoppingCartEntityList = shoppingCartEntity.getGoodsInShoppingCarts(); final DataEntity.ShoppingCartEntity.GoodsInShoppingCartEntity goodsInShoppingCartEntity = shoppingCartEntityList.get(childPosition); if (childPosition == shoppingCartEntity.getGoodsInShoppingCarts().size() - 1) { childHolder.priceAndConfirView.setVisibility(View.VISIBLE); } else { childHolder.priceAndConfirView.setVisibility(View.GONE); } childHolder.shoppingCartCountEditText.setText(goodsInShoppingCartEntity.getChildNum()); childHolder.editShoppingCartCountEditText.setText(goodsInShoppingCartEntity.getChildNum()); final String price = goodsInShoppingCartEntity.getChildPrice(); childHolder.shoppingCartUnitPrice.setText("¥ " + price); childHolder.shoppingCartChildTitle.setText(goodsInShoppingCartEntity.getChildName()); Glide.with(context).load(goodsInShoppingCartEntity.getChildPic()) .diskCacheStrategy(DiskCacheStrategy.SOURCE)//是将图片原尺寸缓存到本地,解决Glide压缩图片偏绿问题 .into(childHolder.imageView); childHolder.addTextView.setClickable(true); childHolder.subTextView.setClickable(true); childHolder.editAddTextView.setClickable(true); childHolder.editSubTextView.setClickable(true); childHolder.shoppingCartChildCheckBox.setClickable(true); childHolder.numberLayout.setVisibility(View.VISIBLE); childHolder.shoppingCartChildCheckBox.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (goodsInShoppingCartEntity.isCheck()) { goodsInShoppingCartEntity.setIsCheck(false); } else { goodsInShoppingCartEntity.setIsCheck(true); } int chekcCount = 0; for (DataEntity.ShoppingCartEntity.GoodsInShoppingCartEntity cartEntity : shoppingCartEntityList) { boolean b = cartEntity.isCheck(); if (b) { chekcCount++; } } if (chekcCount == shoppingCartEntityList.size()) { shoppingCartEntity.setCheck(true); } else { shoppingCartEntity.setCheck(false); } notifyDataSetChanged(); } }); childHolder.shoppingCartChildCheckBox.setChecked(goodsInShoppingCartEntity.isCheck()); childHolder.addTextView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { String s = childHolder.shoppingCartCountEditText.getText().toString().trim(); int count = Integer.parseInt(s) + 1; goodsInShoppingCartEntity.setChildNum(count+""); notifyDataSetChanged(); } }); childHolder.editAddTextView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { String s = childHolder.editShoppingCartCountEditText.getText().toString().trim(); int count = Integer.parseInt(s) + 1; goodsInShoppingCartEntity.setChildNum(count+""); notifyDataSetChanged(); } }); childHolder.subTextView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { String s = childHolder.shoppingCartCountEditText.getText().toString().trim(); int count = Integer.parseInt(s) - 1; if (count > 0) { goodsInShoppingCartEntity.setChildNum(count+""); notifyDataSetChanged(); } } }); childHolder.editSubTextView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { String s = childHolder.editShoppingCartCountEditText.getText().toString().trim(); int count = Integer.parseInt(s) - 1; if (count > 0) { goodsInShoppingCartEntity.setChildNum(count+""); notifyDataSetChanged(); } } }); if (shoppingCartEntity.isEdit()) { childHolder.editView.setVisibility(View.VISIBLE); childHolder.deleteView.setVisibility(View.VISIBLE); childHolder.editAddSubView.setVisibility(View.VISIBLE); childHolder.numberLayout.setVisibility(View.GONE); childHolder.shoppingCartChildTitle.setVisibility(View.GONE); childHolder.shoppingCartUnitPrice.setVisibility(View.GONE); } else { childHolder.editView.setVisibility(View.GONE); childHolder.deleteView.setVisibility(View.GONE); childHolder.shoppingCartChildTitle.setVisibility(View.VISIBLE); childHolder.numberLayout.setVisibility(View.VISIBLE); childHolder.shoppingCartUnitPrice.setVisibility(View.VISIBLE); } childHolder.confirmTextView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //结算请求 } }); double totalPrice = getTotalPrice(shoppingCartEntity.getGoodsInShoppingCarts()); childHolder.shoppingCartPriceTextView.setText("¥ "+totalPrice); childHolder.deleteView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { shoppingCartEntityList.remove(childPosition); notifyDataSetChanged(); } }); return convertView; } @Override public boolean isChildSelectable(int groupPosition, int childPosition) { return false; } class GroupHolder { public CheckBox shoppingCartParentCheckBox; public CheckBox noShoppingCartParentCheckBox; public TextView merchantNameTextView; public TextView editView; } class ChildHolder { View editView; CheckBox shoppingCartChildCheckBox; View addTextView; View subTextView; EditText shoppingCartCountEditText; TextView shoppingCartChildTitle; TextView shoppingCartUnitPrice; ImageView imageView; View deleteView; View editAddTextView; View editSubTextView; EditText editShoppingCartCountEditText; TextView shoppingCartPriceTextView; TextView confirmTextView; View priceAndConfirView; View numberLayout; View editAddSubView; } private double getTotalPrice(List<DataEntity.ShoppingCartEntity.GoodsInShoppingCartEntity> list) { double total = 0d; for (int m = 0; m < list.size(); m++) { DataEntity.ShoppingCartEntity.GoodsInShoppingCartEntity entity = list.get(m); if (entity.isCheck()) { String num = entity.getChildNum(); String price = entity.getChildPrice(); if (!TextUtils.isEmpty(num) && !TextUtils.isEmpty(price)) { int numInt = Integer.parseInt(num); double priceFloat = Double.parseDouble(price); total = Arith.add(total, Arith.mul(numInt, priceFloat)); } } } return total; }}github地址
csdn demo地址
新闻热点
疑难解答