简单版购物车 是用二级列表 框架是MVP 请求网络的方法是OKHttp
以下是效果图
展开后的效果
部分中加减的功能是用自定义view实现的
GitHub地址 https://github.com/zzzzzjson/GoodsListDemo
以下上主要代码
布局文件 MVP框架不在展示
需要的依赖
implementation 'com.github.bumptech.glide:glide:4.8.0'
implementation 'com.google.code.gson:gson:2.8.5'
implementation 'com.squareup.okhttp3:okhttp:3.12.0'
适配器
import android.content.Context;
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 java.util.ArrayList;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.concurrent.ForkJoinPool;
import soexample.umeng.com.androidgoodslist.MyView;
import soexample.umeng.com.androidgoodslist.R;
import soexample.umeng.com.androidgoodslist.bean.MyBean;
public class MyAdapter extends BaseExpandableListAdapter {
private ArrayList list;
private Context context;
public MyAdapter(ArrayList 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) {
groupViewHolder viewHolder = null;
if (convertView == null) {
convertView = View.inflate(context, R.layout.group_view, null);
viewHolder = new groupViewHolder();
viewHolder.Group_ck = convertView.findViewById(R.id.Group_ck);
viewHolder.Group_title = convertView.findViewById(R.id.Group_title);
convertView.setTag(viewHolder);
} else {
viewHolder = (groupViewHolder) convertView.getTag();
}
viewHolder.Group_title.setText(list.get(groupPosition).getName());
boolean childAllCheck = isChildAllCheck(groupPosition);
viewHolder.Group_ck.setChecked(childAllCheck);
viewHolder.Group_ck.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) {
childViewHolder viewHolder = null;
if (convertView == null) {
convertView = View.inflate(context, R.layout.child_view, null);
viewHolder = new childViewHolder();
viewHolder.Child_ck = convertView.findViewById(R.id.Child_ck);
viewHolder.Child_img = convertView.findViewById(R.id.Child_img);
viewHolder.Child_price = convertView.findViewById(R.id.Child_price);
viewHolder.Child_title = convertView.findViewById(R.id.Child_title);
viewHolder.myView = convertView.findViewById(R.id.My_view);
convertView.setTag(viewHolder);
} else {
viewHolder = (childViewHolder) convertView.getTag();
}
viewHolder.Child_title.setText(list.get(groupPosition).getSpus().get(childPosition).getName() + "");
viewHolder.Child_price.setText(list.get(groupPosition).getSpus().get(childPosition).getSkus().get(0).getPrice() + "");
viewHolder.Child_ck.setChecked(list.get(groupPosition).getSpus().get(childPosition).isChildChecked());
viewHolder.myView.setNumber(list.get(groupPosition).getSpus().get(childPosition).getPraise_num());
Glide.with(context).load(list.get(groupPosition).getSpus().get(childPosition).getPic_url()).into(viewHolder.Child_img);
viewHolder.Child_ck.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (adapterCallback != null) {
adapterCallback.setChildCheck(groupPosition, childPosition);
}
}
});
viewHolder.myView.setOnChange(new MyView.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 groupViewHolder {
CheckBox Group_ck;
TextView Group_title;
}
class childViewHolder {
CheckBox Child_ck;
ImageView Child_img;
TextView Child_title;
TextView Child_price;
MyView myView;
}
//因为点击Group和Child第CheckBox在主页面都需要刷新值所以做成接口回调
//整个项目的用到的大致方法 接口回调会使用
public interface AdapterCallback {
//group的按钮
void setGroupCheck(int groupPosition);
//每个child的按钮点击事件
void setChildCheck(int groupPosition, int childPosition);
//加减的点击事件
void setNumber(int groupPosition, int childPosition, int number);
}
private AdapterCallback adapterCallback;
public void setCallback(AdapterCallback adapterCallback) {
this.adapterCallback = adapterCallback;
}
//点击group的CheckBox让所有child选中
//联动 让child跟着group的状态
public void childAllCheck(int groupPosition, boolean isChecked) {
List spus = list.get(groupPosition).getSpus();
for (int i = 0; i < spus.size(); i++) {
spus.get(i).setChildChecked(isChecked);
}
}
//判断group是否被选中的状态
public boolean isChildAllCheck(int groupPosition) {
boolean boo = true;
List spus = list.get(groupPosition).getSpus();
for (int i = 0; i < spus.size(); i++) {
MyBean.DataBean.SpusBean spusBean = spus.get(i);
if (!spusBean.isChildChecked()) {
return false;
}
}
return boo;
}
//点击单独child给他赋值
public void setChildChecked(int groupPosition, int childPosition, boolean isChecked) {
MyBean.DataBean.SpusBean spusBean = list.get(groupPosition).getSpus().get(childPosition);
spusBean.setChildChecked(isChecked);
}
//判断单独的child的选中状态
public boolean isChildChecked(int groupPosition, int childPosition) {
MyBean.DataBean.SpusBean spusBean = list.get(groupPosition).getSpus().get(childPosition);
if (spusBean.isChildChecked()) {
return true;
}
return false;
}
//给商品数量进行赋值
public void setGoodsNumber(int groupPosition, int childPosition, int number) {
list.get(groupPosition).getSpus().get(childPosition).setPraise_num(number);
}
//判断底部视图全选全不选的商品状态
public boolean isAllGoods() {
boolean boo = true;
for (int i = 0; i < list.size(); i++) {
MyBean.DataBean dataBean = list.get(i);
for (int j = 0; j < dataBean.getSpus().size(); j++) {
MyBean.DataBean.SpusBean spusBean = dataBean.getSpus().get(j);
if (!spusBean.isChildChecked()) {
boo = false;
}
}
}
return boo;
}
//实现全选全不选的功能
public void setAllGood(boolean isChecked){
for (int i = 0; i < list.size(); i++) {
MyBean.DataBean dataBean = list.get(i);
for (int j = 0; j < dataBean.getSpus().size(); j++) {
dataBean.getSpus().get(j).setChildChecked(isChecked);
}
}
}
//计算所有商品的数量
public int getAllGoodsNumber(){
int allNumber=0;
for (int i = 0; i < list.size(); i++) {
MyBean.DataBean dataBean = list.get(i);
for (int j = 0; j < dataBean.getSpus().size(); j++) {
MyBean.DataBean.SpusBean spusBean = dataBean.getSpus().get(j);
if (spusBean.isChildChecked()){
allNumber+=spusBean.getPraise_num();
}
}
}
return allNumber;
}
//计算所有商品的价格
public float getAllGoodsPrice(){
float allPrice=0;
for (int i = 0; i < list.size(); i++) {
MyBean.DataBean dataBean = list.get(i);
for (int j = 0; j < dataBean.getSpus().size(); j++) {
MyBean.DataBean.SpusBean spusBean = dataBean.getSpus().get(j);
if (spusBean.isChildChecked()){
allPrice+=spusBean.getPraise_num()*Float.parseFloat(spusBean.getSkus().get(0).getPrice());
}
}
}
return allPrice;
}
}
MainActivity
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.CheckBox;
import android.widget.ExpandableListView;
import android.widget.TextView;
import android.widget.Toast;
import java.util.ArrayList;
import soexample.umeng.com.androidgoodslist.adapter.MyAdapter;
import soexample.umeng.com.androidgoodslist.base.BaseActivity;
import soexample.umeng.com.androidgoodslist.bean.MyBean;
import soexample.umeng.com.androidgoodslist.presenter.PresenterIMpl;
import soexample.umeng.com.androidgoodslist.view.IView;
public class MainActivity extends BaseActivity implements IView {
private ExpandableListView Expand_able;
private CheckBox Check_box;
private TextView Count_sum;
private TextView Count_price;
private PresenterIMpl presenterIMpl;
private ArrayList list = new ArrayList<>();
private MyAdapter myAdapter;
//接口
private String mUrl = "http://www.wanandroid.com/tools/mockapi/6523/restaurant-list";
@Override
protected int getLayout() {
return R.layout.activity_main;
}
@Override
protected void initViews() {
Expand_able = (ExpandableListView) findViewById(R.id.Expand_able);
Check_box = (CheckBox) findViewById(R.id.Check_box);
Count_sum = (TextView) findViewById(R.id.Count_sum);
Count_price = (TextView) findViewById(R.id.Count_price);
//去掉自带的箭头
Expand_able.setGroupIndicator(null);
}
@Override
protected void setOnClick() {
Check_box.setOnClickListener(this);
}
@Override
protected void processLogin() {
presenterIMpl = new PresenterIMpl(this);
myAdapter = new MyAdapter(list, this);
Expand_able.setAdapter(myAdapter);
presenterIMpl.startRequest(mUrl);
myAdapter.setCallback(new MyAdapter.AdapterCallback() {
//组的是否被选中
@Override
public void setGroupCheck(int groupPosition) {
//判断group的状态
boolean childAllCheck = myAdapter.isChildAllCheck(groupPosition);
myAdapter.childAllCheck(groupPosition, !childAllCheck);
myAdapter.notifyDataSetChanged();
flushButtonLayout();
}
@Override
public void setChildCheck(int groupPosition, int childPosition) {
//判断child的状态
boolean childChecked = myAdapter.isChildChecked(groupPosition, childPosition);
myAdapter.setChildChecked(groupPosition, childPosition, !childChecked);
myAdapter.notifyDataSetChanged();
flushButtonLayout();
}
@Override
public void setNumber(int groupPosition, int childPosition, int number) {
myAdapter.setGoodsNumber(groupPosition, childPosition, number);
myAdapter.notifyDataSetChanged();
flushButtonLayout();
}
});
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.Check_box:
//判断底部全选全不选的状态
boolean allGoods = myAdapter.isAllGoods();
myAdapter.setAllGood(!allGoods);
myAdapter.notifyDataSetChanged();
flushButtonLayout();
break;
}
}
@Override
public void success(T user) {
MyBean data = (MyBean) user;
list.addAll(data.getData());
myAdapter.notifyDataSetChanged();
}
@Override
public void error(T error) {
Toast.makeText(this, error + "", Toast.LENGTH_SHORT).show();
}
//释放资源
@Override
protected void onDestroy() {
super.onDestroy();
if (presenterIMpl != null) {
presenterIMpl.onDetach();
}
}
private void flushButtonLayout() {
//上下checkbox联动
boolean allGoods = myAdapter.isAllGoods();
Check_box.setChecked(allGoods);
int allGoodsNumber = myAdapter.getAllGoodsNumber();
float allGoodsPrice = myAdapter.getAllGoodsPrice();
Count_price.setText("合计:"+allGoodsPrice);
Count_sum.setText("去结算(" + allGoodsNumber + ")");
}
}
自定义文件
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;
public class MyView extends LinearLayout implements View.OnClickListener {
private TextView delete_text;
private TextView number_text;
private TextView add_text;
//定义商品数量
private int mCount;
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
LayoutInflater.from(context).inflate(R.layout.my_view, this);
initView();
}
private void initView() {
delete_text=findViewById(R.id.delete_text);
number_text=findViewById(R.id.number_text);
add_text=findViewById(R.id.add_text);
add_text.setOnClickListener(this);
delete_text.setOnClickListener(this);
}
public void setNumber(int number){
this.mCount=number;
number_text.setText(number+"");
}
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.add_text:
mCount++;
number_text.setText(mCount+"");
if (countChange!=null){
countChange.setCount(mCount);
}
break;
case R.id.delete_text:
if (mCount>0){
mCount--;
number_text.setText(mCount+"");
if (countChange!=null){
countChange.setCount(mCount);
}
}else {
Toast.makeText(getContext(), "商品已售空", Toast.LENGTH_SHORT).show();
}
break;
}
}
public interface OnCountChange{
void setCount(int count);
}
private OnCountChange countChange;
public void setOnChange(OnCountChange countChange){
this.countChange=countChange;
}
}
以上二级列表可展开 合住
如果只想要首次加载全部展开,并且点击Group不收缩的效果
可参考 https://blog.csdn.net/jerrywu145/article/details/53014332