布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:orientation="vertical"
android:layout_height="match_parent"
>
<TextView
android:background="@color/colorPrimary"
android:text="购物车"
android:textSize="20dp"
android:textColor="#FFFFFF"
android:textStyle="bold"
android:gravity="center"
android:layout_width="match_parent"
android:layout_height="40dp" />
<ExpandableListView
android:id="@+id/expandView"
android:layout_width="match_parent"
android:layout_weight="1"
android:groupIndicator="@null"
android:layout_height="0dp"/>
<View
android:layout_width="match_parent"
android:layout_height="0.3dp"
android:background="#30b0b0b0"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="40dp">
<CheckBox
android:text="全选"
android:id="@+id/allSelect"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<View
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="1dp"/>
<TextView
android:gravity="center"
android:text="jiage"
android:id="@+id/price"
android:textSize="16sp"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:gravity="center"
android:textColor="#FFFFFF"
android:textStyle="bold"
android:background="#FF0000"
android:layout_marginLeft="20dp"
android:text="jiage"
android:id="@+id/pay"
android:layout_width="100dp"
android:layout_height="match_parent" />
</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">
<CheckBox
android:id="@+id/parent_cb"
android:focusable="false"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/parent_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</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">
<CheckBox
android:id="@+id/child_cb"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<com.facebook.drawee.view.SimpleDraweeView
android:id="@+id/child_drawee"
android:layout_width="60dp"
android:layout_height="80dp" />
<LinearLayout
android:layout_marginLeft="10dp"
android:layout_width="match_parent"
android:layout_height="80dp"
android:orientation="vertical">
<TextView
android:id="@+id/child_title"
android:lines="1"
android:singleLine="true"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
<TextView
android:id="@+id/child_date"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
<LinearLayout
android:layout_marginRight="10dp"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1">
<TextView
android:id="@+id/child_price"
android:layout_width="0dp"
android:gravity="left"
android:layout_height="wrap_content"
android:layout_weight="1" />
<TextView
android:gravity="right"
android:id="@+id/child_num"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
自定义加减布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:gravity="center"
android:layout_width="100dp"
android:layout_height="100dp">
<TextView
android:background="@drawable/bian"
android:gravity="center"
android:id="@+id/jian"
android:text="-"
android:textSize="20dp"
android:textStyle="bold"
android:layout_width="50dp"
android:layout_height="30dp" />
<TextView
android:background="@drawable/bian"
android:id="@+id/num"
android:gravity="center"
android:text="10"
android:textSize="20dp"
android:textStyle="bold"
android:layout_width="60dp"
android:layout_height="30dp" />
<TextView
android:background="@drawable/bian"
android:id="@+id/add"
android:gravity="center"
android:text="+"
android:textSize="20dp"
android:textStyle="bold"
android:layout_width="50dp"
android:layout_height="30dp" />
</LinearLayout>
http包
URL地址
public class ApiConfig {
public static final String baseUrl = "https://www.zhaoapi.cn/";
public static final String index = "ad/getAd";
public static final String cart = "product/getCarts";
public static final String updateCart = "product/updateCarts";
}
服务类
public interface ApiService {
@GET("{url}")
Observable<ResponseBody> doGet(@Path(value = "url",encoded = true) String url, @QueryMap Map<String,String>map);
@FormUrlEncoded
@POST("{url}")
Observable<ResponseBody> doPost(@Path(value = "url",encoded = true) String url, @FieldMap Map<String,String>map);
}
工具类
public class RetrofitUtil {
private static ApiService apiService;
private RetrofitUtil(){
}
public static ApiService getApiService(String baseUrl){
if(apiService == null){
synchronized (RetrofitUtil.class){
if(apiService == null){
initApiService(baseUrl);
}
}
}
return apiService;
}
private static void initApiService(String baseUrl){
apiService = new Retrofit.Builder()
.baseUrl(baseUrl)
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build().create(ApiService.class);
}
}
view包
public interface IView {
void succeed(String json);
void error(Throwable throwable);
}
二级列表适配器
public class ExpandAdapter extends BaseExpandableListAdapter {
private CartBean cartBean;
private Context context;
private AlertDialog alertDialog;
private View alerView;
private int count;
private TextView alertNumView;
public ExpandAdapter(CartBean cartBean, Context context) {
this.cartBean = cartBean;
this.context = context;
initDialog();
}
@Override
public int getGroupCount() {
return cartBean.getData().size();
}
@Override
public int getChildrenCount(int groupPosition) {
return cartBean.getData().get(groupPosition).getList().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(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
if(convertView == null){
convertView = View.inflate(context, R.layout.parent_view,null);
}
final CheckBox cb =convertView.findViewById(R.id.parent_cb);
TextView name = convertView.findViewById(R.id.parent_name);
final CartBean.DataBean dataBean = cartBean.getData().get(groupPosition);
String sellerName = dataBean.getSellerName();
cb.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
boolean checked = cb.isChecked();
setGoodsCheckState(dataBean.getList(),checked);
}
});
boolean checked = dataBean.isChecked();
name.setText(sellerName);
cb.setChecked(checked);
return convertView;
}
@Override
public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
if(convertView == null){
convertView = View.inflate(context, R.layout.child_view,null);
}
final CheckBox cb =convertView.findViewById(R.id.child_cb);
TextView date = convertView.findViewById(R.id.child_date);
TextView price = convertView.findViewById(R.id.child_price);
TextView title = convertView.findViewById(R.id.child_title);
SimpleDraweeView draweeView = convertView.findViewById(R.id.child_drawee);
TextView numView = convertView.findViewById(R.id.child_num);
final CartBean.MyBean myBean = cartBean.getData().get(groupPosition).getList().get(childPosition);
double bargainPrice = myBean.getBargainPrice();
String createtime = myBean.getCreatetime();
final int num = myBean.getNum();
String iconUrl = myBean.getImages().split("\\|")[0];
int selected = myBean.getSelected();
String titleStr = myBean.getTitle();
numView.setText("×"+num);
cb.setChecked(selected == 1?true:false);
date.setText(createtime);
price.setText(bargainPrice+"元");
title.setText(titleStr);
draweeView.setImageURI(Uri.parse(iconUrl));
cb.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
boolean checked = cb.isChecked();
m.clear();
int num = myBean.getNum();
int sellerid = myBean.getSellerid();
int pid = myBean.getPid();
m.put("uid","71");
m.put("pid",""+pid);
m.put("sellerid",sellerid+"");
m.put("num",""+num);
int se = checked ? 1 : 0;
m.put("selected",""+se);
updateCart();
}
});
convertView.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
alertNumView.setText(num+"");
count = num;
alertDialog.show();
m.clear();
int num = myBean.getNum();
int sellerid = myBean.getSellerid();
int pid = myBean.getPid();
m.put("uid","71");
m.put("pid",""+pid);
m.put("sellerid",sellerid+"");
m.put("selected",myBean.getSelected()+"");
return false;
}
});
return convertView;
}
@Override
public boolean isChildSelectable(int groupPosition, int childPosition) {
return true;
}
private Map<String,String> m = new HashMap<>();
public void setGoodsCheckState(List<CartBean.MyBean> list,boolean flag){
Log.e("Flag",flag+"");
for (int i = 0; i < list.size(); i++) {
CartBean.MyBean myBean = list.get(i);
m.clear();
int num = myBean.getNum();
int sellerid = myBean.getSellerid();
int pid = myBean.getPid();
m.put("uid","71");
m.put("pid",""+pid);
m.put("sellerid",sellerid+"");
m.put("num",""+num);
int se = flag ? 1 : 0;
m.put("selected",""+se);
updateCart();
}
}
public void updateCart(){
RetrofitUtil.getApiService(ApiConfig.baseUrl)
.doGet(ApiConfig.updateCart,m)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<ResponseBody>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(ResponseBody responseBody) {
try {
Log.e("resss",responseBody.string());
} catch (IOException e) {
e.printStackTrace();
}finally {
CartActivity.goNet();
}
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
}
});
}
public void initDialog(){
alerView = View.inflate(context, R.layout.alert_view,null);
TextView jian = alerView.findViewById(R.id.jian);
alertNumView = alerView.findViewById(R.id.num);
TextView add = alerView.findViewById(R.id.add);
jian.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(count>0){
count--;
}else{
}
alertNumView.setText(""+count);
}
});
add.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
count++;
alertNumView.setText(""+count);
}
});
alertDialog = new AlertDialog.Builder(context)
.setTitle("修改购买数量")
.setView(alerView)
.setNegativeButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
m.put("num",count+"");
updateCart();
}
})
.setPositiveButton("取消", null)
.create();
}
}
public class MainActivity extends AppCompatActivity implements IView {
@BindView(R.id.mBanner)
MBanner mBanner;
@BindView(R.id.seckill_recycler)
RecyclerView seckillRecycler;
@BindView(R.id.recommend_recycler)
RecyclerView recommendRecycler;
private Unbinder bind;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bind = ButterKnife.bind(this);
PresenterImpl presenter = new PresenterImpl(this);
presenter.getDataFromNet(ApiConfig.index, null);
seckillRecycler.setLayoutManager(new LinearLayoutManager(this, OrientationHelper.HORIZONTAL, false));
recommendRecycler.setLayoutManager(new CustomLinearLayoutManager(this,2));
}
@Override
protected void onDestroy() {
super.onDestroy();
bind.unbind();
}
@Override
public void succeed(String json) {
IndexBean indexBean = new Gson().fromJson(json, IndexBean.class);
ArrayList<String> list = new ArrayList<>();
for (int i = 0; i < indexBean.getData().size(); i++) {
IndexBean.DataBean dataBean = indexBean.getData().get(i);
list.add(dataBean.getIcon());
}
mBanner.setBannerData(list);
seckillRecycler.setAdapter(new SeckillAdapter(indexBean.getMiaosha(), this));
recommendRecycler.setAdapter(new RecommendAdapter(indexBean.getTuijian(),this));
}
@Override
public void error(Throwable throwable) {
Toast.makeText(this, throwable.toString(), Toast.LENGTH_SHORT).show();
}
}
public class CartActivity extends AppCompatActivity implements IView {
private List<CartBean.MyBean> maxList;
private double totalPrice;
private int totalCount;
@BindView(R.id.expandView)
ExpandableListView expandView;
@BindView(R.id.allSelect)
CheckBox allSelect;
@BindView(R.id.price)
TextView price;
@BindView(R.id.pay)
TextView pay;
private Unbinder bind;
private static PresenterImpl presenter;
private int index;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_cart);
bind = ButterKnife.bind(this);
presenter = new PresenterImpl(this);
goNet();
expandView.setOnGroupClickListener(new ExpandableListView.OnGroupClickListener() {
@Override
public boolean onGroupClick(ExpandableListView parent, View v, int groupPosition, long id) {
return true;//返回true,表示不可点击
}
});
}
@OnClick({R.id.allSelect, R.id.pay})
public void onViewClicked(View view) {
switch (view.getId()) {
case R.id.allSelect:
boolean flag = allSelect.isChecked();
index = 0;
updataAllState(flag);
break;
case R.id.pay:
break;
}
}
@Override
public void succeed(String json) {
CartBean cartBean = new Gson().fromJson(json, CartBean.class);
List<CartBean.MyBean> list = cartBean.getData().get(0).getList();
if (list == null || list.size() < 1) {
cartBean.getData().remove(0);
}
setGroudChecked(cartBean);
allSelect.setChecked(isAllChecked(cartBean));
totalPrice();
java.text.DecimalFormat df=new java.text.DecimalFormat("0.00");
String format = df.format(totalPrice)+"元";
pay.setText("去结算("+totalCount+")");
price.setText("合计:"+format);
ExpandAdapter expandAdapter = new ExpandAdapter(cartBean, this);
expandView.setAdapter(expandAdapter);
for (int i = 0; i < expandAdapter.getGroupCount(); i++) {
expandView.expandGroup(i);
}
}
@Override
public void error(Throwable throwable) {
}
@Override
protected void onDestroy() {
super.onDestroy();
bind.unbind();
}
public void setGroudChecked(CartBean cartBean) {
for (int i = 0; i < cartBean.getData().size(); i++) {
CartBean.DataBean dataBean = cartBean.getData().get(i);
boolean flag = checkGroudisChecked(dataBean.getList());
dataBean.setChecked(flag);
}
}
public boolean checkGroudisChecked(List<CartBean.MyBean> list) {
for (int i = 0; i < list.size(); i++) {
int selected = list.get(i).getSelected();
Log.e(selected + "", "AA");
if (selected != 1) {
return false;
}
}
return true;
}
public static void goNet() {
HashMap<String, String> map = new HashMap<>();
map.put("uid", "71");
presenter.getDataFromNet(ApiConfig.cart, map);
}
public boolean isAllChecked(CartBean cartBean) {
maxList = new ArrayList<>();
for (int i = 0; i < cartBean.getData().size(); i++) {
maxList.addAll(cartBean.getData().get(i).getList());
}
for (int i = 0; i < maxList.size(); i++) {
int selected = maxList.get(i).getSelected();
if (selected != 1) {
return false;
}
}
return true;
}
public void updataAllState(final boolean flag){
Map<String,String> m = new HashMap<>();
CartBean.MyBean myBean = maxList.get(index);
String title = myBean.getTitle();
Log.e("TAG",title);
Log.e("msx",maxList.size()+"");
int num = myBean.getNum();
int sellerid = myBean.getSellerid();
int pid = myBean.getPid();
m.put("uid","71");
m.put("pid",""+pid);
m.put("sellerid",sellerid+"");
m.put("num",""+num);
int se = flag ? 1 : 0;
m.put("selected",""+se);
RetrofitUtil.getApiService(ApiConfig.baseUrl)
.doGet(ApiConfig.updateCart,m)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<ResponseBody>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(ResponseBody responseBody) {
try {
Log.e("resss",responseBody.string());
} catch (IOException e) {
e.printStackTrace();
}
if(index == maxList.size()){
goNet();
}else{
Log.e("index",index+"");
updataAllState(flag);
}
index++;
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
}
});
}
public void totalPrice(){
totalPrice = 0;
totalCount = 0;
for (int i = 0; i < maxList.size(); i++) {
CartBean.MyBean myBean = maxList.get(i);
if(myBean.getSelected() == 1){
double bargainPrice = myBean.getBargainPrice();
int num = myBean.getNum();
double price = bargainPrice * num;
totalPrice+=price;
totalCount+=num;
}
}
}
}
model层
bean类
public class CartBean {
private String msg;
private String code;
private List<DataBean> data;
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public List<DataBean> getData() {
return data;
}
public void setData(List<DataBean> data) {
this.data = data;
}
public static class DataBean {
/**
* list : []
* sellerName :
* sellerid : 0
*/
private String sellerName;
private String sellerid;
private List<MyBean> list;
private boolean isChecked;
public boolean isChecked() {
return isChecked;
}
public void setChecked(boolean checked) {
isChecked = checked;
}
public String getSellerName() {
return sellerName;
}
public void setSellerName(String sellerName) {
this.sellerName = sellerName;
}
public String getSellerid() {
return sellerid;
}
public void setSellerid(String sellerid) {
this.sellerid = sellerid;
}
public List<MyBean> getList() {
return list;
}
public void setList(List<MyBean> list) {
this.list = list;
}
}
public static class MyBean{
private double bargainPrice;
private String createtime;
private String detailUrl;
private String images;
private int num;
private int pid;
private double price;
private int pscid;
private int selected;
private int sellerid;
private String subhead;
private String title;
public double getBargainPrice() {
return bargainPrice;
}
public void setBargainPrice(double bargainPrice) {
this.bargainPrice = bargainPrice;
}
public String getCreatetime() {
return createtime;
}
public void setCreatetime(String createtime) {
this.createtime = createtime;
}
public String getDetailUrl() {
return detailUrl;
}
public void setDetailUrl(String detailUrl) {
this.detailUrl = detailUrl;
}
public String getImages() {
return images;
}
public void setImages(String images) {
this.images = images;
}
public int getNum() {
return num;
}
public void setNum(int num) {
this.num = num;
}
public int getPid() {
return pid;
}
public void setPid(int pid) {
this.pid = pid;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public int getPscid() {
return pscid;
}
public void setPscid(int pscid) {
this.pscid = pscid;
}
public int getSelected() {
return selected;
}
public void setSelected(int selected) {
this.selected = selected;
}
public int getSellerid() {
return sellerid;
}
public void setSellerid(int sellerid) {
this.sellerid = sellerid;
}
public String getSubhead() {
return subhead;
}
public void setSubhead(String subhead) {
this.subhead = subhead;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
}
}
Model实现类
public class Model {
private Disposable disposable;
private IPresenter presenter;
public Model(IPresenter presenter) {
this.presenter = presenter;
}
public void getDataFromNet(String url, Map<String, String> map) {
if(map == null){
map = new HashMap<>();
}
map.put("source","android");
RetrofitUtil.getApiService(ApiConfig.baseUrl)
.doGet(url,map)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<ResponseBody>() {
@Override
public void onSubscribe(Disposable d) {
disposable = d;
}
@Override
public void onNext(ResponseBody responseBody) {
try {
String json = responseBody.string();
presenter.succeed(json);
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void onError(Throwable e) {
presenter.error(e);
}
@Override
public void onComplete() {
}
});
}
public void unsubscribe(){
disposable.dispose();
}
}
presenter层
public abstract class BasePresenter<T> {
private Reference<T> mView;
protected void connect(T view){
mView = new WeakReference<>(view);
}
protected boolean isConnect(){
return mView!=null && mView.get()!=null;
}
protected void removeConnect(){
if(isConnect()){
mView.clear();
mView = null;
}
}
}
public interface IPresenter {
void getDataFromNet(String url, Map<String,String> map);
void succeed(String json);
void error(Throwable throwable);
void destroy();
}
public class PresenterImpl extends BasePresenter implements IPresenter {
private Model model;
private IView iView;
public PresenterImpl(IView iView) {
model = new Model(this);
this.iView = iView;
}
@Override
public void getDataFromNet(String url, Map<String, String> map) {
model.getDataFromNet(url,map);
}
@Override
public void succeed(String json) {
iView.succeed(json);
}
@Override
public void error(Throwable throwable) {
iView.error(throwable);
}
@Override
public void destroy() {
model.unsubscribe();
}
}