图片与代码不符
购物车,无非就是对复选框的全选、反选、数量增减,计算价格的一些逻辑
在这里,视图代码就不上了,主要上Adapter适配器的逻辑
在这里,本人使用的是ExpandableListView二级列表展示的,相对来说,逻辑比较清晰一点
下面是适配器里面的主要逻辑代码
//父条目视图View @Override public View getGroupView(final int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) { //使用ViewHolder进行条目优化 MyGroupViewHolder myGroupViewHolder = null; //convertView条目复用 if (convertView == null) { //获取父视图 convertView = LayoutInflater.from(context).inflate(R.layout.group_item, parent, false); CheckBox cb = convertView.findViewById(R.id.group_cb); TextView name = convertView.findViewById(R.id.group_name); myGroupViewHolder = new MyGroupViewHolder(cb, name); convertView.setTag(myGroupViewHolder); } else { myGroupViewHolder = (MyGroupViewHolder) convertView.getTag(); } //初始化父条目数据 myGroupViewHolder.getGroup_cb().setChecked(list.get(groupPosition).isGroupFlag()); myGroupViewHolder.getGroup_name().setText(list.get(groupPosition).getSellerName()); //父条目复选框点击事件 myGroupViewHolder.getGroup_cb().setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //把v强转成CheckBox并获取它的选中状态 CheckBox box = (CheckBox) v; boolean boxChecked = box.isChecked(); //给父条目数据Bean赋值 list.get(groupPosition).setGroupFlag(boxChecked); //判断当复选框选中的时候,记录选中一个 if (boxChecked) { count++; } else { //当它未选中的时候,记录原来选中数如果大于0时的减一 if (count > 0) { count--; } } //获取到子条目数据集合 List<CartBean.ChildBean> childList = MyAdapter.this.list.get(groupPosition).getList(); for (int i = 0; i < childList.size(); i++) { //遍历集合给子条目的复选框选中状态设为父条目复选框的选中状态,父条目及其子条目的全选和反选, childList.get(i).setChildFlag(boxChecked); } //使用自定义接口把获取到的条目选中数量传出去 onGetCount.getCount(count); //调用刷新适配器的方法 setNotifyDataSetChanged(); } }); return convertView; } //子条目视图,优化方式同上,就不一一讲解了 @Override public View getChildView(final int groupPosition, final int childPosition, boolean isLastChild, View convertView, ViewGroup parent) { MyChildViewHolder myChildViewHolder = null; if (convertView == null) { convertView = LayoutInflater.from(context).inflate(R.layout.child_item, parent, false); CheckBox child_cb = convertView.findViewById(R.id.child_cb); SimpleDraweeView child_simple = convertView.findViewById(R.id.child_simple); TextView child_title = convertView.findViewById(R.id.child_title); TextView child_scount = convertView.findViewById(R.id.child_scount); TextView child_delete = convertView.findViewById(R.id.child_delete); SumLayout sumLayout = convertView.findViewById(R.id.sumlayout); myChildViewHolder = new MyChildViewHolder(child_cb, child_simple, child_title, child_scount, child_delete,sumLayout); convertView.setTag(myChildViewHolder); } else { myChildViewHolder = (MyChildViewHolder) convertView.getTag(); } //初始化子条目数据 final List<CartBean.ChildBean> childList = this.list.get(groupPosition).getList(); myChildViewHolder.getChild_cb().setChecked(childList.get(childPosition).isChildFlag()); String images = childList.get(childPosition).getImages().split("\\|")[0]; myChildViewHolder.getChild_simple().setImageURI(images); myChildViewHolder.getChild_title().setText(childList.get(childPosition).getTitle()); myChildViewHolder.getChild_scount().setText(childList.get(childPosition).getSubhead()); //得到数据里面的购买数量 num = list.get(groupPosition).getList().get(childPosition).getNum(); //给视图赋值 myChildViewHolder.getSumLayout().setCount(num+""); //自定义加减框点击事件 final MyChildViewHolder finalMyChildViewHolder1 = myChildViewHolder; myChildViewHolder.getSumLayout().setOnDownSumLayoutListener(new SumLayout.OnDownSumLayouListener() { @Override public void onDownSumLayout() { //得到改变后的购买数量 String count = finalMyChildViewHolder1.getSumLayout().getCount(); //转为int型 int i = Integer.parseInt(count); //并重新给子条目数据的购买数量赋值 list.get(groupPosition).getList().get(childPosition).setNum(i); //调用刷新适配器的方法 setNotifyDataSetChanged(); } }); //删除购物车数据 目前仅仅是删除listview视图 没有删除数据 myChildViewHolder.getChild_delete().setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { List<CartBean.ChildBean> childList = MyAdapter.this.list.get(groupPosition).getList(); childList.remove(childPosition); setNotifyDataSetChanged(); } }); final MyChildViewHolder finalMyChildViewHolder = myChildViewHolder; //子条目复选框点击事件 myChildViewHolder.getChild_cb().setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //得到子条目复选框的选中状态 boolean checked = finalMyChildViewHolder.getChild_cb().isChecked(); //得到子条目数据集合 List<CartBean.ChildBean> childList = MyAdapter.this.list.get(groupPosition).getList(); // 把选中状态赋值给数据集合 childList.get(childPosition).setChildFlag(checked); //判断当为选中状态时选中数量加一 if (checked) { count++; } else {//否则减一 if (count > 0) { count--; } } //设置标记flag 默认为true boolean flag = true; //遍历子条目数据里面的复选框状态,有一个为false,那么父条目数据复选框状态就为false for (int i = 0; i < childList.size(); i++) { boolean childFlag = childList.get(i).isChildFlag(); if (childFlag == false) { flag = false; } } //当子条目复选框全部选中时,父条目复选框,也选中 list.get(groupPosition).setGroupFlag(flag); //使用自定义接口把获取到的条目选中数量传出去 onGetCount.getCount(count); //调用刷新适配器的方法 setNotifyDataSetChanged(); } }); return convertView; } /** * 刷新适配器的方法 */ public void setNotifyDataSetChanged() { //刷洗适配器 notifyDataSetChanged(); //重新请求网络数据 CartPresenterImpl cartPresenter = new CartPresenterImpl(); //请求计算接口 cartPresenter.formJisuan(new CartModelImpl(cartPresenter), iCartView); } //复选框选中个数的内部接口 public interface OnGetCount { void getCount(int count); } //访问接口的放发 public void setOnGetCount(OnGetCount onGetCount) { this.onGetCount = onGetCount; }
我这里使用的是Retrofit+RxJava+MVP进行请求网络数据比较繁琐
Model层接口
public interface ICartModel { //获取购物车数据方法 void formCartDatas(Map<String,String> params); //获取购物车计算价格数据方法 void formCartJisuan(List<CartBean.DataBean> data,ICartPresenter iCartPresenter); }
Model层接口实现类
public class CartModelImpl implements ICartModel { private static final String TAG = "CartModelImpl"; private final ICartPresenter iCartPresenter; //构造方法得到P层的实例 public CartModelImpl(ICartPresenter iCartPresenter) { this.iCartPresenter = iCartPresenter; } //获取购物车数据方法 @Override public void formCartDatas(Map<String, String> params) { //得到网络请求工具类Retrofit+RxJava NetWorkUtils netWorkUtils = NetWorkUtils.getNetWorkUtils(); RtrofitService rtrofitService = netWorkUtils.creatRequest(RtrofitService.class); Observable<CartBean> cartBean = rtrofitService.getCartBean(params); cartBean.subscribeOn(Schedulers.newThread()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Observer<CartBean>() { //请求完成 @Override public void onCompleted() { Log.d(TAG, "onCompleted: 完成"); } //请求失败 @Override public void onError(Throwable e) { Log.d(TAG, "onError: " + e.getMessage()); iCartPresenter.formDataError(e.getMessage()); } //请求中 @Override public void onNext(CartBean cartBean) { Log.d(TAG, "onNext: " + cartBean); String code = cartBean.getCode(); //根据code进行判断 如果code等于0为请求成功 否则请求失败 if (code.equals("0")) { iCartPresenter.formDataSuccess(cartBean.getData()); } else { iCartPresenter.formDataError(cartBean.getMsg()); } } }); } //获取购物车计算价格数据方法 一定是View层返回的集合 @Override public void formCartJisuan(List<CartBean.DataBean> data,ICartPresenter iCartPresenter) { //初始值为0 记录总价 double sum = 0; //遍历父条目数据集合 for (int i = 0; i < data.size(); i++) { //得到子条目数据集合 List<CartBean.ChildBean> childList = data.get(i).getList(); //遍历子条目数据集合 for (int j = 0; j < childList.size(); j++) { //如果,子条目复选框为选中状态时,则累加总价 if (childList.get(j).isChildFlag()){ //得到总价sum 总价=数量*单价 sum+=childList.get(j).getNum()*childList.get(j).getPrice(); } } } Log.d(TAG, "formCartJisuan: "+sum); //把得到的总价传到Presenter层 iCartPresenter.getPrice(sum); }
Presenter层接口
public interface ICartPresenter { //获取Model层和View层方法 和构造方法效果一样 void formDataModelView(ICartModel iCartModel, ICartView iCartView); //获取数据成功方法 void formDataSuccess(List<CartBean.DataBean> data); //获取数据失败方法 void formDataError(String error); //获取计算总价方法 void formJisuan(ICartModel iCartModel,ICartView iCartView); //的到总价方法 void getPrice(double price); }
Presenter层接口实现类
public class CartPresenterImpl implements ICartPresenter { private static final String TAG = "CartPresenterImpl"; private ICartView iCartView; //获取Model层和View层方法 和构造方法效果一样 @Override public void formDataModelView(ICartModel iCartModel, ICartView iCartView) { //得到View层实例 this.iCartView = iCartView; Map<String,String> params = new HashMap<>(); params.put("uid",iCartView.getUid()); //调用Model层获取购物车数据方法 iCartModel.formCartDatas(params); } //获取数据成功方法 @Override public void formDataSuccess(List<CartBean.DataBean> data) { Log.d(TAG, "formDataSuccess: "+data); //调用view层获取数据成功的方法 iCartView.formCartViewSuccess(data); } //获取数据失败方法 @Override public void formDataError(String error) { Log.d(TAG, "formDataError: "+error); //调用view层获取数据失败的方法 iCartView.formCaRTViewError(error); } //获取计算总价方法 @Override public void formJisuan(ICartModel iCartModel, ICartView iCartView) { this.iCartView = iCartView; //调用Model层计算总价的方法 iCartModel.formCartJisuan(iCartView.getList(),this); } //得到总价方法 @Override public void getPrice(double price) { Log.d(TAG, "getPrice: "+price); //把获取到的总价传递给View iCartView.getSum(price); } }
View层接口
public interface ICartView { //获取数据成功方法 void formCartViewSuccess(List<CartBean.DataBean> data); //获取数据失败方法 void formCaRTViewError(String error); //返回UID方法 String getUid(); //获取总价方法 void getSum(double price); //放回购物车数据方法 List<CartBean.DataBean> getList(); }
MainActivity类View层实现类
public class MainActivity extends AppCompatActivity implements ICartView { private static final String TAG = "MainActivity"; @BindView(R.id.main_back) TextView mainBack; @BindView(R.id.expandable) ExpandableListView expandable; @BindView(R.id.main_checkAll) CheckBox mainCheckAll; @BindView(R.id.main_sum) TextView mainSum; @BindView(R.id.main_pay) TextView mainPay; private List<CartBean.DataBean> list; private MyAdapter myAdapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //使用ButterKnife ButterKnife.bind(this); //初始化视图/数据 initViews(); } private void initViews() { //请求网络 CartPresenterImpl cartPresenter = new CartPresenterImpl(); cartPresenter.formDataModelView(new CartModelImpl(cartPresenter), MainActivity.this); } @OnClick({R.id.main_back, R.id.main_checkAll, R.id.main_pay}) public void onViewClicked(View view) { switch (view.getId()) { case R.id.main_back: Toast.makeText(this, "我点击了返回", Toast.LENGTH_SHORT).show(); break; case R.id.main_checkAll://全选复选框点击事件 //得到全选框的选中状态 boolean checked = mainCheckAll.isChecked(); for (int i = 0; i < list.size(); i++) { //遍历购物车数据得到子条目数据集合 把父条目复选框设为全选框状态 list.get(i).setGroupFlag(checked); List<CartBean.ChildBean> childList = this.list.get(i).getList(); for (int j = 0; j < childList.size(); j++) { //把子条目复选框设全选框状态 childList.get(j).setChildFlag(checked); } } //刷洗适配器 myAdapter.notifyDataSetChanged(); //重新计算总价 CartPresenterImpl cartPresenter = new CartPresenterImpl(); //刷新总价 cartPresenter.formJisuan(new CartModelImpl(cartPresenter),this); break; case R.id.main_pay: break; } } // 获取购物车数据成功方法 @Override public void formCartViewSuccess(List<CartBean.DataBean> data) { //把购物车数据提升作用域 this.list = data; Log.d(TAG, "formCartViewSuccess: " + data); //实例化Adapter myAdapter = new MyAdapter(this, data, this); //ExpandableListView设置适配器 expandable.setAdapter(myAdapter); //调用adapter的复选框选中个数的内部接口 myAdapter.setOnGetCount(new MyAdapter.OnGetCount() { @Override public void getCount(int count) { Log.d(TAG, "getCount: " + count); //给TextView赋值 mainPay.setText("去支付(" + count + ")"); } }); //展开子条目 int count = expandable.getCount(); for (int i = 0; i < count; i++) { expandable.expandGroup(i); } } //获取购物车数据失败方法 @Override public void formCaRTViewError(String error) { Log.d(TAG, "formCaRTViewError: " + error); } //返回Uid方法 @Override public String getUid() { return 71 + ""; } //获取总价方法 @Override public void getSum(double price) { Log.d(TAG, "getSum: " + price); mainSum.setText("合计:¥" + price); } //返回购物车数据方法 @Override public List<CartBean.DataBean> getList() { return list; } }
当然,还要有自定义加减框了 SumLayout
public class SumLayout extends LinearLayout implements View.OnClickListener { private TextView sub; private TextView count; private TextView add; private OnDownSumLayouListener onDownSumLayoutListener; //自定义View的构造方法 public SumLayout(Context context) { this(context, null); } public SumLayout(Context context, @Nullable AttributeSet attrs) { this(context, attrs, 0); } public SumLayout(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); //加载视图 View view = View.inflate(context, R.layout.sumlayout, this); //获取控件 sub = view.findViewById(R.id.sub); count = view.findViewById(R.id.count); add = view.findViewById(R.id.add); //注册点击事件 sub.setOnClickListener(this); add.setOnClickListener(this); } //点击事件 @Override public void onClick(View v) { switch (v.getId()) { case R.id.sub://数量减减 //得到数量 String ss = count.getText().toString(); //转为int型 int i = Integer.parseInt(ss); //减减 i--; //判断当i大于等于0时给TextView赋值 if (i >= 0) { setCount(i + ""); //调用自定义接口点击事件 onDownSumLayoutListener.onDownSumLayout(); } break; case R.id.add://数量加加 //获取数量 String s = count.getText().toString(); //转为int型 int i1 = Integer.parseInt(s); //数量加加 i1++; //给数量TextView赋值 setCount(i1 + ""); //调用自定义接口点击事件 onDownSumLayoutListener.onDownSumLayout(); break; } } //给数量TextView赋值的方法 public void setCount(String counts) { count.setText(counts); } //获取数量方法 public String getCount() { return count.getText().toString(); } //自定义接口点击事件 public interface OnDownSumLayouListener { void onDownSumLayout(); } //外部访问接口的方法 public void setOnDownSumLayoutListener(OnDownSumLayouListener onDownSumLayoutListener) { this.onDownSumLayoutListener = onDownSumLayoutListener; } }
别着急下面是自定义组合控件的xml文件 sumlayout.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="wrap_content"> <TextView android:id="@+id/sub" android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center" android:background="@drawable/sumbgcolor" android:text="-"/> <TextView android:id="@+id/count" android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center" android:background="@drawable/sumbgcolor" android:text="0"/> <TextView android:id="@+id/add" android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center" android:background="@drawable/sumbgcolor" android:text="+"/> </LinearLayout>
还有自定义背景的xml文件 sumbgcolor.xml
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"> <stroke android:width="0.1dp" android:color="#000000"></stroke> <size android:width="25dp" android:height="15dp"></size> </shape>