添加依赖
//加载 图片用的包 implementation 'com.nostra13.universalimageloader:universal-image-loader:1.9.5' //Gson implementation 'com.google.code.gson:gson:2.6.2' // OkHttp implementation 'com.squareup.okhttp3:okhttp:3.9.0' //拦截器 implementation 'com.squareup.okhttp3:logging-interceptor:3.9.0'// //recyclerView的依赖 compile 'com.android.support:recyclerview-v7:26+' //xRecyclerView的依赖 compile 'com.jcodecraeer:xrecyclerview:1.5.9' //省去findViewbyid implementation 'com.jakewharton:butterknife:8.8.1' annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1'
添加权限
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
android:name=".app.MyApp"
httpconfig
public class HttpConfig { //京东分类 public static final String CATAGORY_URL = "https://www.zhaoapi.cn/product/getCatagory"; public static final String PRODUCTCATAGORY_URL = "https://www.zhaoapi.cn/product/getProductCatagory"; //购物车接口 public static final String URL_CART="https://www.zhaoapi.cn/product/getCarts?uid=71"; }
OkHttputils
public class OkHttpUtils { public static OkHttpUtils oKhttpUtils; private final OkHttpClient okHttpClient; private final Handler myhandler; private OkHttpUtils() { //日志拦截器 HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor(); httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY); //主线程Handler myhandler = new Handler(Looper.getMainLooper()); okHttpClient = new OkHttpClient.Builder() .readTimeout(5000, TimeUnit.MILLISECONDS) .writeTimeout(5000, TimeUnit.MILLISECONDS) .connectTimeout(5000, TimeUnit.MILLISECONDS) .addInterceptor(httpLoggingInterceptor) .build(); } public static OkHttpUtils getoKhttpUtils() { if (oKhttpUtils == null) { synchronized (OkHttpUtils.class) { if (oKhttpUtils == null) { return oKhttpUtils = new OkHttpUtils(); } } } return oKhttpUtils; } //异步get public void doGet(String url, final IOKhttpUtilsCallback ioKhttpUtilsCallback) { Request request = new Request.Builder() .get() .url(url) .build(); Call call = okHttpClient.newCall(request); call.enqueue(new Callback() { @Override public void onFailure(Call call, final IOException e) { if (ioKhttpUtilsCallback != null) { //切换到主线程 myhandler.post(new Runnable() { @Override public void run() { ioKhttpUtilsCallback.onFailure(e.getMessage()); } }); } } @Override public void onResponse(Call call, Response response) throws IOException { if (response != null && response.isSuccessful()) { final String json = response.body().string(); if (ioKhttpUtilsCallback != null) { //切换到主线程 myhandler.post(new Runnable() { @Override public void run() { ioKhttpUtilsCallback.onResponse(json); } }); } } else { if (ioKhttpUtilsCallback != null) { //切换到主线程 myhandler.post(new Runnable() { @Override public void run() { ioKhttpUtilsCallback.onFailure("网络异常"); } }); } } } }); } //异步post public void doPost(String url, Map<String, String> map, final IOKhttpUtilsCallback ioKhttpUtilsCallback) { FormBody.Builder builder = new FormBody.Builder(); for (Map.Entry<String, String> entry : map.entrySet()) { builder.add(entry.getKey(), entry.getValue()); } FormBody formBody = builder.build(); Request request = new Request.Builder() .post(formBody) .url(url) .build(); Call call = okHttpClient.newCall(request); call.enqueue(new Callback() { @Override public void onFailure(Call call, final IOException e) { if (ioKhttpUtilsCallback != null) { //切换到主线程 myhandler.post(new Runnable() { @Override public void run() { ioKhttpUtilsCallback.onFailure(e.getMessage()); } }); } } @Override public void onResponse(Call call, Response response) throws IOException { if (response != null && response.isSuccessful()) { final String json = response.body().string(); if (ioKhttpUtilsCallback != null) { //切换到主线程 myhandler.post(new Runnable() { @Override public void run() { ioKhttpUtilsCallback.onResponse(json); } }); } } else { if (ioKhttpUtilsCallback != null) { //切换到主线程 myhandler.post(new Runnable() { @Override public void run() { ioKhttpUtilsCallback.onFailure("网络异常"); } }); } } } }); } //接口回调 public interface IOKhttpUtilsCallback { void onFailure(String error); void onResponse(String json); } }
activity_cart 主布局
<?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"> <ExpandableListView android:id="@+id/cart_expand" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_marginBottom="50dp"></ExpandableListView> <LinearLayout android:layout_width="match_parent" android:layout_height="60sp" android:layout_alignParentBottom="true"> <CheckBox android:id="@+id/quanxuan" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="全选" /> <TextView android:id="@+id/he" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="20dp" android:layout_weight="1" android:text="合计:¥0.0" /> <Button android:id="@+id/btn_buy" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="去结算()" /> </LinearLayout> </RelativeLayout>
父级xml cart_parent
<?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="60sp" android:layout_gravity="center_vertical" > <CheckBox android:id="@+id/seller_cb" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <TextView android:id="@+id/seller_name_tv" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="20dp" android:text="文字" /> </LinearLayout>
子级xml cart_child
<?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" > <CheckBox android:id="@+id/child_cb" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <ImageView android:id="@+id/product_img" android:layout_width="80dp" android:layout_height="80dp" android:layout_marginLeft="20dp" android:src="@mipmap/ic_launcher" /> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <TextView android:id="@+id/product_title_name_tv" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="商品标题" /> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <TextView android:id="@+id/child_price" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="¥0.0" /> </LinearLayout> <com.example.moni.mvp.cart.view.MyAddSub android:id="@+id/my_sub_add" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="15dp"></com.example.moni.mvp.cart.view.MyAddSub> </LinearLayout> </LinearLayout>
加减号xml my_sub_add
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="60sp" android:layout_height="30dp" android:layout_gravity="center_vertical" android:gravity="center_vertical" android:layout_marginLeft="15dp" > <TextView android:id="@+id/jian" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="-" android:background="#fff" android:gravity="center" android:layout_weight="1" /> <TextView android:id="@+id/product_num" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="1" android:layout_weight="1" android:background="#fff" android:gravity="center" /> <TextView android:id="@+id/jia" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:background="#fff" android:text="+" /> </LinearLayout>
model层 cartmodel
public class CartModel { public void getCart(final onCallBack onCallBack) { String url = HttpConfig.URL_CART; OkHttpUtils.getoKhttpUtils().doGet(url, new OkHttpUtils.IOKhttpUtilsCallback() { @Override public void onFailure(String error) { if (onCallBack != null) { onCallBack.onFaild("错了"); } } @Override public void onResponse(String json) { Gson gson = new Gson(); CartBean cartBean = gson.fromJson(json, CartBean.class); String code = cartBean.getCode(); if ("0".equalsIgnoreCase(code)) { if (onCallBack != null) { onCallBack.onSuccess(cartBean); } } } }); } public interface onCallBack { void onSuccess(CartBean cartBean); void onFaild(String error); } }
presenter层 cartpresenter
public class CartPresenter extends BasePresenter<CartView>{ private CartModel cartModel; public CartPresenter(CartView view) { super(view); } @Override protected void initmodel() { cartModel = new CartModel(); } public void doCart() { cartModel.getCart(new CartModel.onCallBack() { @Override public void onSuccess(CartBean cartBean) { if (view != null) { view.onSuccess(cartBean); } } @Override public void onFaild(String error) { if (view != null) { view.onFaild(error); } } }); } }
view层 cartView
public interface CartView extends IView { void onSuccess(CartBean cartBean); void onFaild(String error); } 加载加减号的类 mysubadd
public class MyAddSub extends LinearLayout{ @BindView(R.id.jian) TextView jian; @BindView(R.id.product_num) TextView productNum; @BindView(R.id.jia) TextView jia; int number = 1; public MyAddSub(Context context) { this(context, null); } public MyAddSub(Context context, @Nullable AttributeSet attrs) { super(context, attrs); View view = inflate(context, R.layout.my_sub_add, this); //初始化 ButterKnife.bind(view); } @OnClick({R.id.jian, R.id.product_num, R.id.jia}) public void onViewClicked(View view) { switch (view.getId()) { case R.id.jian: if (number > 1) { --number; productNum.setText(number + ""); if (onNumberChangeListener != null) { onNumberChangeListener.onSubNumberChange(number); } } else { Toast.makeText(getContext(), "数量不能小于1", Toast.LENGTH_SHORT).show(); } break; case R.id.jia: ++number; productNum.setText(number + ""); if (onNumberChangeListener != null) { onNumberChangeListener.onAddNumberChange(number); } break; } } public int getNumber() { return number; } public void setNumber(int number) { this.number = number; productNum.setText(number + ""); } private onNumberChangeListener onNumberChangeListener; public void setOnNumberChangeListener(MyAddSub.onNumberChangeListener onNumberChangeListener) { this.onNumberChangeListener = onNumberChangeListener; } public interface onNumberChangeListener { void onAddNumberChange(int product_num); void onSubNumberChange(int product_num); } }
购物车的适配器 ExpandViewAdapter
public class ExpandViewAdapter extends BaseExpandableListAdapter { private List<CartBean.DataBean> seller; private static final String TAG = "适配器********"; public ExpandViewAdapter(List<CartBean.DataBean> seller) { this.seller = seller; } @Override public int getGroupCount() { return seller == null ? 0 : seller.size(); } @Override public int getChildrenCount(int groupPosition) { return seller.get(groupPosition).getList().size(); } @Override public Object getGroup(int groupPosition) { return seller.get(groupPosition); } @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) { CartBean.DataBean dataBean = seller.get(groupPosition); ParentHolder parentHolder; if (convertView == null) { convertView = View.inflate(parent.getContext(), R.layout.cart_parent, null); parentHolder = new ParentHolder(convertView); convertView.setTag(parentHolder); } else { parentHolder = (ParentHolder) convertView.getTag(); } //赋值商家名称 Log.d(TAG, "getGroupView: "+dataBean.getSellerName()); parentHolder.sellerNameTv.setText(dataBean.getSellerName()); boolean b = productStatus(groupPosition); parentHolder.sellerCb.setChecked(b); parentHolder.sellerCb.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (onCartListChangeListener != null) { onCartListChangeListener.SellerCheckChange(groupPosition); } } }); return convertView; } @SuppressLint("SetTextI18n") @Override public View getChildView(final int groupPosition, final int childPosition, boolean isLastChild, View convertView, final ViewGroup parent) { CartBean.DataBean.ListBean listBean = seller.get(groupPosition).getList().get(childPosition); ChildHolder childHolder; if (convertView == null) { convertView = View.inflate(parent.getContext(), R.layout.cart_child, null); childHolder = new ChildHolder(convertView); convertView.setTag(childHolder); } else { childHolder = (ChildHolder) convertView.getTag(); } //赋值子类名称 childHolder.productTitleNameTv.setText(listBean.getTitle()); childHolder.childPrice.setText(listBean.getPrice() + ""); String[] pic = listBean.getImages().split("\\|"); ImageLoader.getInstance().displayImage(pic[0], childHolder.productImg, MyApp.getOptions()); boolean flag = listBean.getSelected() == 1 ? true : false; childHolder.childCb.setChecked(flag); ; childHolder.childCb.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (onCartListChangeListener != null) { onCartListChangeListener.onProductCheckedChange(groupPosition, childPosition); Toast.makeText(parent.getContext(), "kkkkk", Toast.LENGTH_SHORT).show(); } } }); childHolder.mySubAdd.setNumber(listBean.getNum()); childHolder.mySubAdd.setOnNumberChangeListener(new MyAddSub.onNumberChangeListener() { @Override public void onAddNumberChange(int product_num) { if (onCartListChangeListener != null) { onCartListChangeListener.onProductNumberChange(groupPosition, childPosition, product_num); } } @Override public void onSubNumberChange(int product_num) { if (onCartListChangeListener != null) { onCartListChangeListener.onProductNumberChange(groupPosition, childPosition, product_num); } } }); return convertView; } @Override public boolean isChildSelectable(int groupPosition, int childPosition) { return true; } //关于商家按钮 public boolean productStatus(int groupPosition) { List<CartBean.DataBean.ListBean> list = seller.get(groupPosition).getList(); for (CartBean.DataBean.ListBean listBean : list) { if (listBean.getSelected() == 0) { return false; } } return true; } //子类按钮跟着改变 public void noProductStatus(int groupPosition, boolean b) { List<CartBean.DataBean.ListBean> list = seller.get(groupPosition).getList(); for (int i = 0; i < list.size(); i++) { list.get(i).setSelected(b ? 1 : 0); } } //判断所有商品是否选中 public boolean isAllProductSelected() { for (int i = 0; i < seller.size(); i++) { List<CartBean.DataBean.ListBean> list = seller.get(i).getList(); for (int j = 0; j < list.size(); j++) { if (list.get(j).getSelected() == 0) { return false; } } } return true; } //关于底部全选按钮 public void changeAllProductStatus(boolean selected) { for (int i = 0; i < seller.size(); i++) { List<CartBean.DataBean.ListBean> list = seller.get(i).getList(); for (int j = 0; j < list.size(); j++) { list.get(j).setSelected(selected ? 1 : 0); } } } //关于子类按钮 public void changeCurrentProductStatus(int groupPosition, int childPosition) { List<CartBean.DataBean.ListBean> list = seller.get(groupPosition).getList(); CartBean.DataBean.ListBean listBean = list.get(childPosition); listBean.setSelected(listBean.getSelected() == 0 ? 1 : 0); } //总价格 public float calcuteTotalPrice() { float totlaPrice = 0; for (int i = 0; i < seller.size(); i++) { List<CartBean.DataBean.ListBean> list = seller.get(i).getList(); for (int j = 0; j < list.size(); j++) { if (list.get(j).getSelected() == 1) { float price = list.get(j).getPrice(); int num = list.get(j).getNum(); totlaPrice += num * price; } } } return totlaPrice; } //总数量 public int cacuteTotalNum() { int totalNum = 0; for (int i = 0; i < seller.size(); i++) { List<CartBean.DataBean.ListBean> list = seller.get(i).getList(); for (int j = 0; j < list.size(); j++) { if (list.get(j).getSelected() == 1) { int num = list.get(j).getNum(); totalNum += num; } } } return totalNum; } //设置加减按钮 public void changeCurrentNumberProduct(int groupPosition, int childPosition, int number) { List<CartBean.DataBean.ListBean> list = seller.get(groupPosition).getList(); CartBean.DataBean.ListBean listBean = list.get(childPosition); listBean.setNum(number); } //总价格 //父类 static class ParentHolder { @BindView(R.id.seller_cb) CheckBox sellerCb; @BindView(R.id.seller_name_tv) TextView sellerNameTv; ParentHolder(View view) { ButterKnife.bind(this, view); } } //子类 onCartListChangeListener onCartListChangeListener; public void setOnCartListChangeListener(ExpandViewAdapter.onCartListChangeListener onCartListChangeListener) { this.onCartListChangeListener = onCartListChangeListener; } //接口回调 public interface onCartListChangeListener { void SellerCheckChange(int groupPosition); void onProductCheckedChange(int groupPosition, int childPosition); void onProductNumberChange(int groupPosition, int childPosition, int number); } static class ChildHolder { @BindView(R.id.child_cb) CheckBox childCb; @BindView(R.id.product_img) ImageView productImg; @BindView(R.id.product_title_name_tv) TextView productTitleNameTv; @BindView(R.id.child_price) TextView childPrice; @BindView(R.id.my_sub_add) MyAddSub mySubAdd; ChildHolder(View view) { ButterKnife.bind(this, view); } } }
购物车的fragment
public class CartFragment extends BaseFragment<CartPresenter> implements CartView,View.OnClickListener { private CheckBox quanxuan; private ExpandableListView expandableListView; private Button btn_buy; private TextView he; private ExpandViewAdapter adapter; @Override public void onClick(View v) { //底部全选按钮 boolean allProductSelected = adapter.isAllProductSelected(); adapter.changeAllProductStatus(!allProductSelected); //刷新适配器 adapter.notifyDataSetChanged(); reFreshSelectedAndToTalPriceAndTotalAllNumber(); } @Override public Context context() { return getActivity(); } @Override public void onSuccess(CartBean cartBean) { List<CartBean.DataBean> data = cartBean.getData(); //创建适配器 adapter = new ExpandViewAdapter(data); expandableListView.setAdapter(adapter); adapter.setOnCartListChangeListener(new ExpandViewAdapter.onCartListChangeListener() { @Override public void SellerCheckChange(int groupPosition) { //设置商家 boolean b = adapter.productStatus(groupPosition); //子类按钮跟着改变 adapter.noProductStatus(groupPosition, !b); //刷新适配器 adapter.notifyDataSetChanged(); reFreshSelectedAndToTalPriceAndTotalAllNumber(); } @Override public void onProductCheckedChange(int groupPosition, int childPosition) { adapter.changeCurrentProductStatus(groupPosition, childPosition); //刷新适配器 adapter.notifyDataSetChanged(); reFreshSelectedAndToTalPriceAndTotalAllNumber(); } @Override public void onProductNumberChange(int groupPosition, int childPosition, int number) { //设置加减按钮 adapter.changeCurrentNumberProduct(groupPosition, childPosition, number); //刷新适配器 adapter.notifyDataSetChanged(); reFreshSelectedAndToTalPriceAndTotalAllNumber(); } }); //展开二级列表 for (int i = 0; i < data.size(); i++) { expandableListView.expandGroup(i); } reFreshSelectedAndToTalPriceAndTotalAllNumber(); } @Override public void onFaild(String error) { } @Override protected void initViews(View view) { //获取id quanxuan = view.findViewById(R.id.quanxuan); expandableListView = view.findViewById(R.id.cart_expand); btn_buy = view.findViewById(R.id.btn_buy); he = view.findViewById(R.id.he); quanxuan.setOnClickListener(this); } @Override protected void initData() { presenter.doCart(); } @Override protected void initListener() { } @Override protected CartPresenter providePresenter() { return new CartPresenter(this); } @Override protected int privideLayoutId() { return R.layout.activity_cart; } public void reFreshSelectedAndToTalPriceAndTotalAllNumber() { //判断是否全部选中 boolean allProductSelected = adapter.isAllProductSelected(); quanxuan.setChecked(allProductSelected); //刷新适配器 //adapter.notifyDataSetChanged(); // reFreshSelectedAndToTalPriceAndTotalAllNumber(); //设置总价格 float totalPrice = adapter.calcuteTotalPrice(); he.setText("总价格(" + totalPrice + ")"); //总数量 int totalNum = adapter.cacuteTotalNum(); btn_buy.setText("总数量" + totalNum); } }