二级列表实现购物车,使用OkHttpClient请求数据
2018-12-18 21:30
381 查看
二级列表做购物车最难的就是关联,需要判断,逻辑比较绕,但只要自己好好看看,理解理解还是会感到很简单的。
先看效果,再说代码
如果要把所有的不同都上传就太多了,所有这里就先放3张图片
在做功能之前,我们应该先把要使用的依赖导入,权限加上
//因为我们要从网上获取数据,所以导入okhttp,然后用gson解析,用glide加载图片 implementation 'com.google.code.gson:gson:2.8.5' implementation 'com.squareup.okhttp3:okhttp:3.12.0' implementation 'com.github.bumptech.glide:glide:4.8.0'
然后在清单文件中添加权限
<uses-permission android:name="android.permission.INTERNET" />
现在先写activity.xml文件
<RelativeLayout 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" tools:context=".MainActivity"> <LinearLayout android:id="@+id/send_footer" android:layout_width="match_parent" android:layout_height="40dp" android:layout_alignParentBottom="true" android:orientation="horizontal"> <CheckBox android:id="@+id/send_all" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:focusable="false" android:text="全选" android:textSize="20sp" /> <TextView android:id="@+id/send_price" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="2" android:gravity="center" android:text="价格:0.0" android:textSize="20sp" /> <TextView android:id="@+id/send_sum" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="2" android:gravity="center" android:text="总数量:0" android:textSize="20sp" /> </LinearLayout> <ExpandableListView android:id="@+id/send_expand" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_above="@id/send_footer"></ExpandableListView> </RelativeLayout>
一级的xml文件视图
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal"> <CheckBox android:id="@+id/group_check" android:layout_width="wrap_content" android:layout_height="wrap_content" android:focusable="false" android:textSize="35sp" /> <TextView android:id="@+id/group_title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="35sp" /> </LinearLayout>
二级的xml文件的视图
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <CheckBox android:id="@+id/child_check" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="25sp" /> <ImageView android:id="@+id/child_image" android:layout_width="200dp" android:layout_height="200dp" android:layout_toRightOf="@id/child_check" /> <TextView android:id="@+id/child_title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_toRightOf="@id/child_image" android:textSize="25sp" /> <TextView android:id="@+id/child_price" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_toRightOf="@id/child_title" android:textColor="#f00" android:textSize="25sp" /> //自定义的控件 <com.bwie.lian.weight.MyView android:id="@+id/child_myview" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@id/child_title" android:layout_toRightOf="@id/child_image"></com.bwie.lian.weight.MyView> </RelativeLayout>
在这里有一个自定义的控件
在自定义之前要有一个xml文件,里面有两张图片,可以用自己的来替换。它的效果如下:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal"> <ImageView android:id="@+id/send_jia" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/jia" /> <TextView android:id="@+id/send_number" android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center" android:text="0" android:textSize="35sp" /> <ImageView android:id="@+id/send_jian" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/jian" /> </LinearLayout>
现在就应该写一个类,来自定义
public class MyView extends LinearLayout implements View.OnClickListener { private ImageView send_jia; private TextView send_number; private ImageView send_jian; private int mNumber; private Context mContext; public MyView(Context context, AttributeSet attrs) { super(context, attrs); this.mContext = context; //获取视图 LayoutInflater.from(context).inflate(R.layout.number_list, this); //查找控件 initView(); } //定义一个方法来获取商品数量 public void setChildNumber(int number) { this.mNumber = number; send_number.setText("数量是:" + mNumber); } private void initView() { send_jia = findViewById(R.id.send_jia); send_jia.setOnClickListener(this); send_number = findViewById(R.id.send_number); send_jian = findViewById(R.id.send_jian); send_jian.setOnClickListener(this); } @Override public void onClick(View view) { //判断点击事件 switch (view.getId()) { case R.id.send_jian: //减得时候数量要大于0 if (mNumber > 0) { mNumber--; //给TextView赋值 send_number.setText("数量是:" + mNumber); //判断接口是否为空 if (onChangeChildCount != null) { //将改完的数量传入接口中 onChangeChildCount.getChildCount(mNumber); } } else { //提示 Toast.makeText(mContext, "数量最小为0", Toast.LENGTH_SHORT).show(); } break; case R.id.send_jia: //跟减的意思一样 mNumber++; send_number.setText("数量是:" + mNumber); if (onChangeChildCount != null) { onChangeChildCount.getChildCount(mNumber); } break; } } //自定义接口 public interface OnChangeChildCount { void getChildCount(int number); } private OnChangeChildCount onChangeChildCount; public void setOnChangeChildCount(OnChangeChildCount onChangeChildCount) { this.onChangeChildCount = onChangeChildCount; } }
现在是MainActivity中的代码
public class MainActivity extends AppCompatActivity { //网络请求的数据存入集合中 private List<ShopBean.DataBean> mdata = new ArrayList<>(); private String mUrl = "http://www.wanandroid.com/tools/mockapi/6523/restaurant-list"; private CheckBox send_all; private TextView send_price; private TextView send_sum; private ExpandableListView send_expand; private MyAdapter adapter; @SuppressLint("HandlerLeak") //使用handler,在里面解析字符串,重新赋值,刷新适配器 private Handler handler = new Handler() { @Override public void handleMessage(Message msg) { String jsonStr = (String) msg.obj; Gson gson = new Gson(); ShopBean shopBean = gson.fromJson(jsonStr, ShopBean.class); mdata.addAll(shopBean.getData()); adapter.notifyDataSetChanged(); } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //查找控件 initView(); //配置适配器 adapter = new MyAdapter(mdata, MainActivity.this); send_expand.setAdapter(adapter); //网络请求数据 getData(); //实现适配器中的接口 adapter.setAdapterAllCallBack(new MyAdapter.AdapterAllCallBack() { //group的checkbox点击事件 @Override public void setGroupChecked(int groupPosition) { //判断组内的子成员的checkbox是否全部选中 boolean childs = adapter.AllChildIsChecked(groupPosition); //如果是true,那再点击group的checkbox就是实现全不选,所有要!一下 //如果是false,则于此想反 adapter.setGroupChecked(groupPosition, !childs); //刷新适配器 20000 adapter.notifyDataSetChanged(); //每次有所改变时,都要刷新一下底部视图 FlushFooterLayout(); } @Override public void setChildChecked(int groupPosition, int childPosition) { //判断当前子成员的checkbox是否选中 boolean chlid = adapter.thisChildIsChecked(groupPosition, childPosition); //如果是true,那再点击checkbox就是实现不选,所有要!一下 //如果是false,则于此想反 adapter.setChildChecked(groupPosition, childPosition, !chlid); //刷新适配器 adapter.notifyDataSetChanged(); //每次有所改变时,都要刷新一下底部视图 FlushFooterLayout(); } @Override public void setFooterNumber(int groupPosition, int childPosition, int number) { adapter.setShopCount(groupPosition, childPosition, number); //刷新适配器 adapter.notifyDataSetChanged(); //每次有所改变时,都要刷新一下底部视图 FlushFooterLayout(); } }); send_all.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { //判断所有的商品是否全部选中 boolean b = adapter.thisAllShopsIsChecked(); //如果是true,那再点击checkbox就是实现全不选,所有要!一下 //如果是false,则于此想反 adapter.setAllShopsChecked(!b); //刷新适配器 adapter.notifyDataSetChanged(); //每次有所改变时,都要刷新一下底部视图 FlushFooterLayout(); } }); } //刷新底部视图 public void FlushFooterLayout() { //判断所有的商品是否全部选中,根据返回值给底部的checkbox设置上 boolean b = adapter.thisAllShopsIsChecked(); send_all.setChecked(b); //获取数量,价格,显示出来 int allShopNumbers = adapter.getAllShopNumbers(); float allShopPrices = adapter.getAllShopPrices(); send_price.setText("总价格:¥" + allShopPrices); send_sum.setText("总数量:" + allShopNumbers); } //网络获取数据 private void getData() { //这是异步的get请求方式 OkHttpClient okHttpClient = new OkHttpClient(); Request request = new Request.Builder().url(mUrl).build(); okHttpClient.newCall(request).enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { } @Override public void onResponse(Call call, Response response) throws IOException { //将数据发送到handler中 handler.sendMessage(handler.obtainMessage(1, response.body().string())); } }); } //获取控件 private void initView() { send_all = (CheckBox) findViewById(R.id.send_all); send_price = (TextView) findViewById(R.id.send_price); send_sum = (TextView) findViewById(R.id.send_sum); send_expand = (ExpandableListView) findViewById(R.id.send_expand); send_expand.setGroupIndicator(null); } }
然后是适配器中的内容
二级列表的适配器要继承BaseExpandableListAdapter并重写方法
public class MyAdapter extends BaseExpandableListAdapter { //用构造器传来数据和上下文 private List<ShopBean.DataBean> data; private Context context; public MyAdapter(List<ShopBean.DataBean> data, Context context) { this.data = data; this.context = context; } //返回组的个数 @Override public int getGroupCount() { return data.size(); } //返回子成员的个数 @Override public int getChildrenCount(int i) { return data.get(i).getSpus().size(); } @Override public Object getGroup(int i) { return null; } @Override public Object getChild(int i, int i1) { return null; } @Override public long getGroupId(int i) { return 0; } @Override public long getChildId(int i, int i1) { return 0; } @Override public boolean hasStableIds() { return false; } //组的视图,跟listview适配器中getview()方法写的东西一样 @Override public View getGroupView(final int groupPosition, boolean b, View view, ViewGroup viewGroup) { GroupHolder holder = null; if (view == null) { //查找视图,控件 view = View.inflate(context, R.layout.group_list, null); holder = new GroupHolder(); holder.group_check = view.findViewById(R.id.group_check); holder.group_title = view.findViewById(R.id.group_title); view.setTag(holder); } else { holder = (GroupHolder) view.getTag(); } //赋值 holder.group_title.setText(data.get(groupPosition).getName()); //调用方法AllChildIsChecked(groupPosition)来返回一个值,如果子成员全选中则为true,否则为false holder.group_check.setChecked(AllChildIsChecked(groupPosition)); //checkbox的点击事件 holder.group_check.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { //判断是否为空 if (adapterAllCallBack != null) { //为group的方法传入参数 adapterAllCallBack.setGroupChecked(groupPosition); } } }); return view; } @Override public View getChildView(final int groupPosition, final int childPosition, boolean b, View view, ViewGroup viewGroup) { ChildHolder holder = null; if (view == null) { view = View.inflate(context, R.layout.child_list, null); holder = new ChildHolder(); holder.child_check = view.findViewById(R.id.child_check); holder.child_image = view.findViewById(R.id.child_image); holder.child_title = view.findViewById(R.id.child_title); holder.child_price = view.findViewById(R.id.child_price); holder.child_myview = view.findViewById(R.id.child_myview); view.setTag(holder); } else { holder = (ChildHolder) view.getTag(); } //glide加载图片 Glide.with(context).load(data.get(groupPosition).getSpus().get(childPosition).getPic_url()).into(holder.child_image); //赋值 holder.child_title.setText(data.get(groupPosition).getSpus().get(childPosition).getName()); holder.child_price.setText("¥:" + data.get(groupPosition).getSpus().get(childPosition).getSkus().get(0).getPrice()); holder.child_check.setChecked(data.get(groupPosition).getSpus().get(childPosition).isChildChecked()); //checkbox的点击事件 holder.child_check.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { if (adapterAllCallBack != null) { //给child的方法传入参数 adapterAllCallBack.setChildChecked(groupPosition, childPosition); } } }); //这是调用自定义控件的方法和接口 //将集合中的数量传入 holder.child_myview.setChildNumber(data.get(groupPosition).getSpus().get(childPosition).getPraise_num()); //控件的点击事件 holder.child_myview.setOnChangeChildCount(new MyView.OnChangeChildCount() { @Override public void getChildCount(int number) { if (adapterAllCallBack != null) { //不为空时,传入参数 adapterAllCallBack.setFooterNumber(groupPosition, childPosition, number); } } }); return view; } @Override public boolean isChildSelectable(int i, int i1) { return false; } //group class GroupHolder { CheckBox group_check; TextView group_title; } //child class ChildHolder { CheckBox child_check; ImageView child_image; TextView child_title; TextView child_price; MyView child_myview; } //点击组的checkbox,来实现全选,全不选 public void setGroupChecked(int groupPosition, boolean childChecked) { List<ShopBean.DataBean.SpusBean> spus = data.get(groupPosition).getSpus(); for (int i = 0; i < spus.size(); i++) { ShopBean.DataBean.SpusBean spusBean = spus.get(i); spusBean.setChildChecked(childChecked); } } //判断组内的child的checkbox是否选中 public boolean AllChildIsChecked(int groupPosition) { List<ShopBean.DataBean.SpusBean> spus = data.get(groupPosition).getSpus(); for (int i = 0; i < spus.size(); i++) { boolean childChecked = spus.get(i).isChildChecked(); if (!childChecked) { return false; } } return true; } //根据已存在的状态,判断这次点击后的child中checkbox中状态 public void setChildChecked(int groupPosition, int childPosition, boolean childChecked) { List<ShopBean.DataBean.SpusBean> spus = data.get(groupPosition).getSpus(); for (int i = 0; i < spus.size(); i++) { ShopBean.DataBean.SpusBean spusBean = spus.get(childPosition); spusBean.setChildChecked(childChecked); } } //判断当前的child中的checkbox是否选中 public boolean thisChildIsChecked(int groupPosition, int childPosition) { List<ShopBean.DataBean.SpusBean> spus = data.get(groupPosition).getSpus(); for (int i = 0; i < spus.size(); i++) { ShopBean.DataBean.SpusBean spusBean = spus.get(childPosition); boolean childChecked = spusBean.isChildChecked(); if (!childChecked) { return false; } } return true; } //根据判断,设置全选,全不选 public void setAllShopsChecked(boolean childChecked) { for (int i = 0; i < data.size(); i++) { ShopBean.DataBean dataBean = data.get(i); for (int j = 0; j < dataBean.getSpus().size(); j++) { ShopBean.DataBean.SpusBean spusBean = dataBean.getSpus().get(j); spusBean.setChildChecked(childChecked); } } } //判断所有的商品是否选中 public boolean thisAllShopsIsChecked() { for (int i = 0; i < data.size(); i++) { ShopBean.DataBean dataBean = data.get(i); for (int j = 0; j < dataBean.getSpus().size(); j++) { ShopBean.DataBean.SpusBean spusBean = dataBean.getSpus().get(j); if (!spusBean.isChildChecked()) { return false; } } } return true; } //给商品数量赋值 public void setShopCount(int groupPosition, int childPosition, int number) { data.get(groupPosition).getSpus().get(childPosition).setPraise_num(number); } //计算商品价格 public float getAllShopPrices() { float mSum = 0; for (int i = 0; i < data.size(); i++) { ShopBean.DataBean dataBean = data.get(i); for (int j = 0; j < dataBean.getSpus().size(); j++) { ShopBean.DataBean.SpusBean spusBean = dataBean.getSpus().get(j); if (spusBean.isChildChecked()) { mSum += spusBean.getPraise_num() * Float.parseFloat(spusBean.getSkus().get(0).getPrice()); } } } return mSum; } //计算商品数量 public int getAllShopNumbers() { int mSum = 0; for (int i = 0; i < data.size(); i++) { ShopBean.DataBean dataBean = data.get(i); for (int j = 0; j < dataBean.getSpus().size(); j++) { ShopBean.DataBean.SpusBean spusBean = dataBean.getSpus().get(j); if (spusBean.isChildChecked()) { mSum += spusBean.getPraise_num(); } } } return mSum; } //自定义接口 public interface AdapterAllCallBack { //group点击时调用的方法 void setGroupChecked(int groupPosition); //child点击时调用的方法 void setChildChecked(int groupPosition, int childPosition); //自定义控件点击时调用的方法 void setFooterNumber(int groupPosition, int childPosition, int number); } private AdapterAllCallBack adapterAllCallBack; public void setAdapterAllCallBack(AdapterAllCallBack adapterAllCallBack) { this.adapterAllCallBack = adapterAllCallBack; } }
好了到现在,代码就写完了,虽然有点多,但也不要害怕,要一点一点理解。
相关文章推荐
- RecyclerView条目跳转+SpringView数据刷新加载+MVP+OKhttp+拦截器+自定义view 实现请求网络数据的二级列表购物车
- MVP+OKhttp+拦截器+RecyclerView+自定义view 实现请求网络数据的二级列表购物车
- 购物车二级列表的实现,在一级列表基础上,bean类里再添加两个字段(请求本地json数据)
- android(21)(使用HttpURLConnection,HttpClient和AsyncHttpClient分别实现post和get请求数据)
- 购物车二级列表的实现,在一级列表基础上,bean类里再添加两个字段(请求本地json数据)
- 安卓使用OkHttpClient进行网络请求
- 简单实现 二级列表购物车(固定数据)
- 使用ExpandListView二级列表实现购物车
- OkHttpClient post请求今日头条数据 RecycleView显示
- 模仿京东购物车(二级列表,mvp请求数据)
- 使用rxjava,retrofit,okhttp实现mvp模式的数据解析
- android菜鸟学习笔记24----与服务器端交互(一)使用HttpURLConnection和HttpClient请求服务端数据
- 使用AsyncHttpClient框架来完成网络数据的请求
- 使用AsycHttpClient请求Tomcat的新闻客户端的实现
- 使用recycleview,okhttp实现购物车
- 网络请求数据添加到列表(okhttp+RecyclerView)
- 使用MVP,recycleview,okhttp生成二级购物车。
- Mvp设计模式实现okHttpClient请求展示在RecycleView
- java使用common-httpclient包实现post请求方法示例
- OkHttpClient请求数据