購物車---二級列表---詳細註釋
activity_main
<?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/ex_listView" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="10" /> <LinearLayout android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" android:orientation="horizontal"> <CheckBox android:id="@+id/all_box" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:text="全選" /> <TextView android:id="@+id/all_price" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:text="總價:¥0.00" android:textSize="18sp" /> <Button android:id="@+id/jiesuan_btn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:text="結算" /> </LinearLayout> </LinearLayout>
加減器 add_sub_item
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="80dp" android:layout_height="40dp" android:orientation="horizontal"> <TextView android:id="@+id/sub_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:text="-" android:textSize="20sp" /> <TextView android:id="@+id/num_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:text="1" android:textSize="20sp" /> <TextView android:id="@+id/add_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:text="+" android:textSize="20sp" /> </LinearLayout>
組佈局 parent_item
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="80dp" android:layout_height="40dp" android:orientation="horizontal"> <CheckBox android:id="@+id/box_parent" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center"/> <TextView android:id="@+id/text_parent" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="商家" android:textSize="20sp" android:layout_gravity="center"/> </LinearLayout>
子佈局 child_item
<?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">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<CheckBox
android:id="@+id/child_box"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"/>
<ImageView
android:id="@+id/child_image"
android:layout_width="100dp"
android:layout_height="100dp"
android:padding="10dp"
android:src="@mipmap/ic_launcher" />
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_weight="1">
<TextView
android:id="@+id/child_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingTop="15dp"
android:text="jhsjhdsk"
android:textSize="17sp" />
<TextView
android:id="@+id/child_price"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingTop="10dp"
android:text="¥0.0" />
</LinearLayout>
<wanghuiqi.bawie.com.whq_shop.view.MyAddSub
android:id="@+id/add_sub"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:gravity="center_vertical" />
</LinearLayout>
加減器 MyAddSub
package wanghuiqi.bawie.com.whq_shop.view;
import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.widget.ExpandableListView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import wanghuiqi.bawie.com.whq_shop.R;
public class MyAddSub extends LinearLayout implements View.OnClickListener {
private TextView addText;
private TextView subText;
private TextView numText;
private int number = 1;
public MyAddSub(Context context) {
this(context, null);
}
public MyAddSub(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public MyAddSub(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
View view = inflate(context, R.layout.add_sub_item, this);
addText = view.findViewById(R.id.add_text);
subText = view.findViewById(R.id.sub_text);
numText = view.findViewById(R.id.num_text);
addText.setOnClickListener(this);
subText.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.add_text:
++number;
numText.setText(number + "");
if (mOnNumberChangeInterface != null) {
mOnNumberChangeInterface.onNumberChang(number);
}
break;
case R.id.sub_text:
//判斷如果數字比1大就減,比1小就吐司
if (number > 1) {
--number;
numText.setText(number + "");
if (mOnNumberChangeInterface != null) {
mOnNumberChangeInterface.onNumberChang(number);
}
} else {
Toast.makeText(getContext(), "不能再少了", Toast.LENGTH_SHORT).show();
}
break;
}
}
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
numText.setText(number + "");
}
//建立介面
public interface OnNumberChangeInterface {
void onNumberChang(int num);
}
//宣告介面名
private OnNumberChangeInterface mOnNumberChangeInterface;
//暴露方法
public void setOnNumberChangeInterface(OnNumberChangeInterface onNumberChangeInterface) {
mOnNumberChangeInterface = onNumberChangeInterface;
}
}
adapter ShopAdapter
package wanghuiqi.bawie.com.whq_shop.adapter;
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.squareup.picasso.Picasso;
import java.util.List;
import wanghuiqi.bawie.com.whq_shop.R;
import wanghuiqi.bawie.com.whq_shop.model.bean.Shop;
import wanghuiqi.bawie.com.whq_shop.view.MyAddSub;
public class ShopAdapter extends BaseExpandableListAdapter {
private List<Shop.DataBean> shopData;
public ShopAdapter(List<Shop.DataBean> shopData) {
this.shopData = shopData;
}
//1.有多少按鈕
@Override
public int getGroupCount() {
return shopData.size();
}
//2.一個組裡有多少子條目
@Override
public int getChildrenCount(int groupPosition) {
return shopData.get(groupPosition).getList().size();
}
////////P.組佈局////////
@Override
public View getGroupView(final int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
//P1.獲取組的下標
Shop.DataBean dataBean = shopData.get(groupPosition);
ParentHolder parentHolder;
if (convertView == null) {
convertView = View.inflate(parent.getContext(), R.layout.parent_item, null);
parentHolder = new ParentHolder(convertView);
convertView.setTag(parentHolder);
} else {
parentHolder = (ParentHolder) convertView.getTag();
}
//P2.獲取商家名稱
parentHolder.textParent.setText(dataBean.getSellerName());
//P3.根據當前商家的所有商品,確定checkbox是否選中
boolean parentAllSelect = isParentAllSelect(groupPosition);
//P4.1根據boolean判斷是否選中
parentHolder.boxParent.setChecked(parentAllSelect);
//P5.設定點選checkbox的點選事件,介面回撥
parentHolder.boxParent.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mOnCartListChangeListener != null) {
mOnCartListChangeListener.onParentCheckedChange(groupPosition);
}
}
});
return convertView;
}
////////////C.子佈局///////////
@Override
public View getChildView(final int groupPosition, final int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
Shop.DataBean dataBean = shopData.get(groupPosition);
List<Shop.DataBean.ListBean> list = dataBean.getList();
//C1.拿到list集合裡具體商品
Shop.DataBean.ListBean listBean = list.get(childPosition);
ChildHolder childHolder;
if (convertView == null) {
convertView = View.inflate(parent.getContext(), R.layout.child_item, null);
childHolder = new ChildHolder(convertView);
convertView.setTag(childHolder);
} else {
childHolder = (ChildHolder) convertView.getTag();
}
//C2.擷取圖片picasso
String images = listBean.getImages();
String[] strings = images.split("!");
Picasso.with(parent.getContext()).load(strings[0]).into(childHolder.imageChild);
//C.獲取商品名稱
childHolder.childText.setText(listBean.getTitle());
//C.單價
childHolder.childPrice.setText(listBean.getPrice() + "");
//C.設定子條目複選框是否選中
childHolder.boxChild.setChecked(listBean.getSelected() == 1);
//C.設定加減器內部數量
childHolder.addSub.setNumber(listBean.getNum());
//C3.設定商品checkbox的點選事件,介面回撥
childHolder.boxChild.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mOnCartListChangeListener != null) {
mOnCartListChangeListener.onChildCheckedChange(groupPosition, childPosition);
}
}
});
//C4.設定加減器的點選事件,介面回撥
childHolder.addSub.setOnNumberChangeInterface(new MyAddSub.OnNumberChangeInterface() {
@Override
public void onNumberChang(int num) {
if (mOnCartListChangeListener != null) {
mOnCartListChangeListener.onAddSubNumberChange(groupPosition, childPosition, num);
}
}
});
return convertView;
}
//--------判斷當前商品是否被選中--------
public boolean isParentAllSelect(int groupPosition) {
//拿到組的資料
Shop.DataBean dataBean = shopData.get(groupPosition);
//拿到商家所有商品,集合
List<Shop.DataBean.ListBean> list = dataBean.getList();
for (int i = 0; i < list.size(); i++) {
//判斷這個組所有商品是否被選中,如有一個未選中就都不選中
if (list.get(i).getSelected() == 0) {
return false;
}
}
return true;
}
//------底部全選按鈕邏輯判斷------
public boolean isAllSelected() {
for (int i = 0; i < shopData.size(); i++) {
Shop.DataBean dataBean = shopData.get(i);
List<Shop.DataBean.ListBean> list = dataBean.getList();
for (int j = 0; j < list.size(); j++) {
//判斷組的商品是否被選中
if (list.get(j).getSelected() == 0) {
return false;
}
}
}
return true;
}
//-----計算商品總數量-----
public int TotalNumber() {
int totalNumber = 0;
for (int i = 0; i < shopData.size(); i++) {
Shop.DataBean dataBean = shopData.get(i);
List<Shop.DataBean.ListBean> list = dataBean.getList();
for (int j = 0; j < list.size(); j++) {
//商品數量,選中的
if (list.get(j).getSelected() == 1) {
//拿到商品的數量
int num = list.get(j).getNum();
totalNumber += num;
}
}
}
return totalNumber;
}
//-------計算商品總價格-------
public float TotalPrice() {
float totalPrice = 0;
for (int i = 0; i < shopData.size(); i++) {
Shop.DataBean dataBean = shopData.get(i);
List<Shop.DataBean.ListBean> list = dataBean.getList();
for (int j = 0; j < list.size(); j++) {
//商品價格,選中的
if (list.get(j).getSelected() == 1) {
//拿到商品數量
double price = list.get(j).getPrice();
int num = list.get(j).getNum();
totalPrice += price + num;
}
}
}
return totalPrice;
}
//--------根據選擇,更改選框裡狀態------
public void changeSellerAllProduct(int groupPosition, boolean isSelected) {
Shop.DataBean dataBean = shopData.get(groupPosition);
List<Shop.DataBean.ListBean> list = dataBean.getList();
for (int i = 0; i < list.size(); i++) {
Shop.DataBean.ListBean listBean = list.get(i);
listBean.setSelected(isSelected ? 1 : 0);
}
}
//---------當子條目選中,更新組選框的狀態-------
public void changeChild(int groupPosition, int childPosition) {
Shop.DataBean dataBean = shopData.get(groupPosition);
List<Shop.DataBean.ListBean> list = dataBean.getList();
Shop.DataBean.ListBean listBean = list.get(childPosition);
listBean.setSelected(listBean.getSelected() == 0 ? 1 : 0);
}
//---------當最底部全選框選中,更新所有選框的狀態
public void changAllCheckBox(boolean selected) {
for (int i = 0; i < shopData.size(); i++) {
Shop.DataBean dataBean = shopData.get(i);
List<Shop.DataBean.ListBean> list = dataBean.getList();
for (int j = 0; j < list.size(); j++) {
list.get(j).setSelected(selected ? 1 : 0);
}
}
}
//----------當加減器被點選時,改變商品數量--------
public void changProductNumber(int groupPosition, int childPosition, int number){
Shop.DataBean dataBean = shopData.get(groupPosition);
List<Shop.DataBean.ListBean> list = dataBean.getList();
Shop.DataBean.ListBean listBean = list.get(childPosition);
listBean.setNum(number);
}
//==============Viewhodler============
//組的Viewholder
public static class ParentHolder {
private final CheckBox boxParent;
private final TextView textParent;
public ParentHolder(View rootView) {
boxParent = rootView.findViewById(R.id.box_parent);
textParent = rootView.findViewById(R.id.text_parent);
}
}
public static class ChildHolder {
private final CheckBox boxChild;
private final ImageView imageChild;
private final TextView childText;
private final TextView childPrice;
private final MyAddSub addSub;
public ChildHolder(View rootView) {
boxChild = rootView.findViewById(R.id.child_box);
imageChild = rootView.findViewById(R.id.child_image);
childText = rootView.findViewById(R.id.child_text);
childPrice = rootView.findViewById(R.id.child_price);
addSub = rootView.findViewById(R.id.add_sub);
}
}
//=============建立介面===========
public interface onCartListChangeListener {
/*當組的checkbox點選時回撥*/
void onParentCheckedChange(int groupPosition);
/*當點選子條目商品的checkbox回撥*/
void onChildCheckedChange(int groupPosition, int childPosition);
/*當點選加減按鈕的回撥*/
void onAddSubNumberChange(int groupPosition, int childPosition, int number);
}
private onCartListChangeListener mOnCartListChangeListener;
public void setOnCartListChangeListener(onCartListChangeListener onCartListChangeListener) {
mOnCartListChangeListener = onCartListChangeListener;
}
//不管這些
@Override
public boolean isChildSelectable(int groupPosition, int childPosition) {
return false;
}
@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;
}
}
工具類 HttpUtils
package wanghuiqi.bawie.com.whq_shop.model;
import android.os.Handler;
import android.os.Looper;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
public class HttpUtils {
private final Handler handler;
private final OkHttpClient httpClient;
private static HttpUtils mHttpUtils;
private HttpUtils(){
//建立主執行緒的handler
handler = new Handler(Looper.getMainLooper());
httpClient = new OkHttpClient.Builder()
.connectTimeout(500, TimeUnit.MILLISECONDS)
.readTimeout(5000, TimeUnit.MILLISECONDS)
.writeTimeout(5000, TimeUnit.MILLISECONDS)
.build();
}
//建立介面
public interface OKhttpInterface{
void Failed(Exception e);
void Success(String data);
}
public void doGet(String url, final OKhttpInterface mOkhttpInterface){
Request request = new Request.Builder()
.get()
.url(url)
.build();
httpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, final IOException e) {
if (mOkhttpInterface!=null){
//切換到主執行緒
handler.post(new Runnable() {
@Override
public void run() {
mOkhttpInterface.Failed(e);
}
});
}
}
@Override
public void onResponse(Call call, Response response) throws IOException {
if (response!=null&&response.isSuccessful()){
final String data = response.body().string();
handler.post(new Runnable() {
@Override
public void run() {
if (mOkhttpInterface!=null){
mOkhttpInterface.Success(data);
return;
}
}
});
}
}
});
}
//單例模式
public static HttpUtils getInstance(){
if (mHttpUtils==null){
synchronized (HttpUtils.class){
if (mHttpUtils==null){
return mHttpUtils=new HttpUtils();
}
}
}
return mHttpUtils;
}
}
ShopPresenter P層
package wanghuiqi.bawie.com.whq_shop.presenter;
import com.google.gson.Gson;
import java.util.List;
import wanghuiqi.bawie.com.whq_shop.model.HttpUtils;
import wanghuiqi.bawie.com.whq_shop.model.bean.Shop;
public class ShopPresenter {
public void ShopData(String url) {
HttpUtils.getInstance().doGet(url, new HttpUtils.OKhttpInterface() {
@Override
public void Failed(Exception e) {
mOnshopInterface.failed(e);
}
@Override
public void Success(String data) {
Shop shop = new Gson().fromJson(data, Shop.class);
List<Shop.DataBean> shopData = shop.getData();
mOnshopInterface.success(shopData);
}
});
}
public interface onShopInterface {
void failed(Exception e);
void success(List<Shop.DataBean> shopData);
}
private onShopInterface mOnshopInterface;
public void setOnshopInterface(onShopInterface onshopInterface) {
mOnshopInterface = onshopInterface;
}
}
MainActivity
package wanghuiqi.bawie.com.whq_shop;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.ExpandableListView;
import android.widget.TextView;
import java.util.List;
import wanghuiqi.bawie.com.whq_shop.adapter.ShopAdapter;
import wanghuiqi.bawie.com.whq_shop.model.bean.Shop;
import wanghuiqi.bawie.com.whq_shop.presenter.ShopPresenter;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private ExpandableListView ex_listView;
private CheckBox all_box;
private TextView all_price;
private Button jiesuan_btn;
private ShopAdapter shopAdapter;
private String url = "http://www.zhaoapi.cn/product/getCarts?uid=71";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//A.獲取控制元件
initView();
//B.獲取資料
initData();
}
//B.獲取資料
private void initData() {
ShopPresenter shopPresenter = new ShopPresenter();
shopPresenter.ShopData(url);
shopPresenter.setOnshopInterface(new ShopPresenter.onShopInterface() {
@Override
public void failed(Exception e) {
}
@Override
public void success(List<Shop.DataBean> shopData) {
//B1.獲取介面卡
shopAdapter = new ShopAdapter(shopData);
//B2.對介面卡設定監聽(加減器,組,子條目複選框改變)
shopAdapter.setOnCartListChangeListener(new ShopAdapter.onCartListChangeListener() {
//------B2.1.組的複選框被點選------
@Override
public void onParentCheckedChange(int groupPosition) {
boolean parentAllSelect = shopAdapter.isParentAllSelect(groupPosition);
shopAdapter.changeSellerAllProduct(groupPosition, !parentAllSelect);
shopAdapter.notifyDataSetChanged();
//重新整理底部
refreshAllShop();
}
//-------B2.2.子條目的複選框被點選-------
@Override
public void onChildCheckedChange(int groupPosition, int childPosition) {
shopAdapter.changeChild(groupPosition, childPosition);
shopAdapter.notifyDataSetChanged();
refreshAllShop();
}
//-------B2.3.加減器被點選------
@Override
public void onAddSubNumberChange(int groupPosition, int childPosition, int number) {
shopAdapter.changProductNumber(groupPosition, childPosition, number);
shopAdapter.notifyDataSetChanged();
refreshAllShop();
}
});
//B3.設定adapter物件
ex_listView.setAdapter(shopAdapter);
//B4.展開二級列表
for (int i=0;i<shopData.size();i++){
ex_listView.expandGroup(i);
}
}
});
}
//-------底部全選框的點選事件--------
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.all_box:
boolean allSelected = shopAdapter.isAllSelected();
shopAdapter.changAllCheckBox(!allSelected);
shopAdapter.notifyDataSetChanged();
//重新整理底部的資料顯示
refreshAllShop();
break;
}
}
//--------重新整理底部---------
private void refreshAllShop() {
//判斷是否所有商品都被選中
boolean allSelected = shopAdapter.isAllSelected();
//設定給checkbox
all_box.setChecked(allSelected);
//計算總計
float price = shopAdapter.TotalPrice();
all_price.setText("總計" + price);
//計算數量
int number = shopAdapter.TotalNumber();
jiesuan_btn.setText("去結算(" + number + ")");
}
//A.初始化控制元件
private void initView() {
ex_listView = findViewById(R.id.ex_listView);
all_box = findViewById(R.id.all_box);
all_price = findViewById(R.id.all_price);
jiesuan_btn = findViewById(R.id.jiesuan_btn);
all_box.setOnClickListener(this);
}
}