网络权限
加减不能连续按
入口函数
compile 'com.squareup.okhttp3:okhttp:3.9.0' compile 'com.google.code.gson:gson:2.8.2' compile 'com.android.support:recyclerview-v7:25.2.0' compile 'com.nostra13.universalimageloader:universal-image-loader:1.9.5'
CustomJiaJian 这个自定义view 需要添加导入 其中更改项目名
import static com.example.gwc01.R.id.count; item 布局 自定义view部分需要自己重写
布局
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="com.example.gwclx.MainActivity"> <android.support.v7.widget.RecyclerView android:id="@+id/recycler_View" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" /> <LinearLayout android:gravity="center_vertical" android:padding="10dp" android:orientation="horizontal" android:layout_alignParentBottom="true" android:layout_width="match_parent" android:layout_height="wrap_content"> <CheckBox android:background="@drawable/no" android:button="@null" android:id="@+id/quanxuan" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <TextView android:textStyle="bold" android:layout_marginLeft="10dp" android:textSize="23sp" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="全选" /> <LinearLayout android:padding="10dp" android:layout_marginLeft="10dp" android:orientation="vertical" android:layout_width="0dp" android:layout_weight="1" android:layout_height="wrap_content"> <TextView android:textColor="#e53e42" android:id="@+id/total_price" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="20sp" android:text="总价 : ¥0元" /> <TextView android:id="@+id/total_num" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="20sp" android:text="共0件商品" /> </LinearLayout> <TextView android:gravity="center" android:textSize="25sp" android:text="去结算" android:textColor="#fff" android:background="@color/colorPrimary" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </LinearLayout> </LinearLayout>/
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="match_parent" android:padding="15dp" android:orientation="vertical" > <LinearLayout android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="wrap_content"> <CheckBox android:id="@+id/shop_checkbox" android:layout_width="50dp" android:layout_height="50dp" /> <TextView android:layout_marginLeft="20dp" android:text="良品铺子" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="23sp" android:textStyle="bold" android:id="@+id/shop_name" /> </LinearLayout> <LinearLayout android:gravity="center_vertical" android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="wrap_content"> <CheckBox android:id="@+id/item_checkbox" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <ImageView android:id="@+id/item_face" android:src="@mipmap/ic_launcher" android:layout_width="120dp" android:layout_height="120dp" /> <LinearLayout android:layout_marginLeft="10dp" android:orientation="vertical" android:layout_width="0dp" android:layout_weight="1" android:layout_height="wrap_content"> <TextView android:id="@+id/item_name" android:textSize="20sp" android:text="三只松鼠" android:layout_width="wrap_content" android:layout_weight="1" android:layout_height="0dp" /> <TextView android:textColor="#f00" android:id="@+id/item_price" android:textSize="23sp" android:text="299" android:layout_width="wrap_content" android:layout_height="0dp" android:layout_weight="1" /> <com.example.gwclx.CustomJiaJian android:id="@+id/custom_jiajian" android:layout_width="wrap_content" android:layout_height="0dp" android:layout_weight="1"></com.example.gwclx.CustomJiaJian> </LinearLayout> <ImageView android:id="@+id/item_delete" android:layout_marginRight="10dp" android:src="@drawable/delete" android:layout_width="30dp" android:layout_height="30dp" /> </LinearLayout> </LinearLayout>/
计算的布局
plusminus
<?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="wrap_content" android:gravity="center_vertical" > <Button android:background="#fff" android:textSize="20sp" android:id="@+id/reverse" android:text="-" android:layout_width="50dp" android:layout_height="wrap_content" /> <EditText android:textStyle="bold" android:textSize="23sp" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="1" android:id="@+id/count" /> <Button android:id="@+id/add" android:background="#fff" android:textSize="25sp" android:text="+" android:layout_width="50dp" android:layout_height="wrap_content" /> </LinearLayout>/
入口函数
package com.example.gwclx; import android.app.Application; import com.nostra13.universalimageloader.core.ImageLoader; import com.nostra13.universalimageloader.core.ImageLoaderConfiguration; /** * Created by Administrator on 2018/1/7 0007. */ public class Rukou extends Application { @Override public void onCreate() { super.onCreate(); ImageLoaderConfiguration configuration = new ImageLoaderConfiguration.Builder(this).build(); ImageLoader.getInstance().init(configuration); } }//
MainActivity
package com.example.gwclx; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.view.View; import android.widget.CheckBox; import android.widget.TextView; import android.widget.Toast; import com.example.gwclx.adapter.RecyAdapter; import com.example.gwclx.callBack.ViewCallBack; import com.example.gwclx.presenter.MyPresenter; public class MainActivity extends AppCompatActivity implements ViewCallBack { private RecyclerView recyclerView; private TextView total_price; private TextView total_num; private CheckBox quanxuan; private MyPresenter myPresenter; private RecyAdapter recyAdapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); recyclerView = (RecyclerView) findViewById(R.id.recycler_View); total_price = (TextView) findViewById(R.id.total_price); total_num = (TextView) findViewById(R.id.total_num); quanxuan = (CheckBox) findViewById(R.id.quanxuan); quanxuan.setTag(1);//1为不选中 LinearLayoutManager manager = new LinearLayoutManager(MainActivity.this,LinearLayoutManager.VERTICAL,false); //new出适配器 recyAdapter = new RecyAdapter(this); myPresenter = new MyPresenter(this); //调用presenter里面的请求数据的方法 myPresenter.getData(); recyclerView.setLayoutManager(manager); recyclerView.setAdapter(recyAdapter); //调用recyAdapter里面的接口,设置 全选按钮 总价 总数量 recyAdapter.setUpdateListener(new RecyAdapter.UpdateListener() { @Override public void setTotal(String total, String num, boolean allCheck) { //设置ui的改变 total_num.setText("共"+num+"件商品");//总数量 total_price.setText("总价 :¥"+total+"元");//总价 if(allCheck){ quanxuan.setTag(2); quanxuan.setBackgroundResource(R.drawable.yes); }else{ quanxuan.setTag(1); quanxuan.setBackgroundResource(R.drawable.no); } quanxuan.setChecked(allCheck); } }); //这里只做ui更改, 点击全选按钮,,调到adapter里面操作 quanxuan.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //调用adapter里面的方法 ,,把当前quanxuan状态传递过去 int tag = (int) quanxuan.getTag(); if(tag==1){ quanxuan.setTag(2); quanxuan.setBackgroundResource(R.drawable.yes); }else{ quanxuan.setTag(1); quanxuan.setBackgroundResource(R.drawable.no); } recyAdapter.quanXuan(quanxuan.isChecked()); } }); } //实现接口,重写的方法 public void success(CartBean cartBean) { //拿到返回来的数据 ,, 传给适配器数据 recyAdapter.add(cartBean); } public void failure(final Exception e) { runOnUiThread(new Runnable() { @Override public void run() { Toast.makeText(MainActivity.this,"error",Toast.LENGTH_SHORT).show(); } }); } @Override protected void onDestroy() { super.onDestroy(); //调用p层的解除绑定 myPresenter.detach(); } }/
自定义控件 加减的类 CustomJiaJian
package com.example.gwclx; import android.content.Context; import android.util.AttributeSet; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.LinearLayout; import static com.example.gwclx.R.id.count; /** * Created by Administrator on 2018/1/7 0007. */ public class CustomJiaJian extends LinearLayout{ private Button reverse; private Button add; private EditText countEdit; private int mCount=1; public CustomJiaJian(Context context) { super(context); } public CustomJiaJian(Context context, AttributeSet attrs) { super(context, attrs); View view = View.inflate(context, R.layout.plusminus,this); reverse = (Button) view.findViewById(R.id.reverse); add = (Button) view.findViewById(R.id.add); countEdit = (EditText) view.findViewById(count); reverse.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { String content = countEdit.getText().toString().trim(); try { int count = Integer.valueOf(content); if(count>1){ mCount = count-1; countEdit.setText(mCount+""); //回调给adapter里面 if(customListener!=null){ customListener.jiajian(mCount); } } } catch (Exception e) { e.printStackTrace(); } } }); add.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { String content = countEdit.getText().toString().trim(); try { int count = Integer.valueOf(content)+1; mCount = count; countEdit.setText(mCount+""); //接口回调给adapter if(customListener!=null){ customListener.jiajian(mCount); } } catch (Exception e) { e.printStackTrace(); } } }); } public CustomJiaJian(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } CustomListener customListener; public void setCustomListener(CustomListener customListener){ this.customListener = customListener; } //加减的接口 public interface CustomListener{ public void jiajian(int count); public void shuRuZhi(int count); } //这个方法是供recyadapter设置 数量时候调用的 public void setEditText(int num) { if(countEdit !=null) { countEdit.setText(num + ""); } } }//
Bean类 先生成网址的数据 再加入以下三个 (加三遍) CartBean
- private int isFirst = 1;//1为显示商铺, 2为隐藏商铺
- private boolean item_check;//每个商品的选中状态
- private boolean shop_check;//商店的选中状态
- public int getIsFirst() {
- return isFirst;
- }
- public void setIsFirst(int isFirst) {
- this.isFirst = isFirst;
- }
- public boolean isItem_check() {
- return item_check;
- }
- public void setItem_check(boolean item_check) {
- this.item_check = item_check;
- }
- public boolean isShop_check() {
- return shop_check;
- }
- public void setShop_check(boolean shop_check) {
- this.shop_check = shop_check;
- }
适配器RecyAdapter
package com.example.gwclx.adapter; import android.content.Context; import android.support.v7.widget.RecyclerView; import android.view.View; import android.view.ViewGroup; import android.widget.CheckBox; import android.widget.ImageView; import android.widget.TextView; import com.example.gwclx.CartBean; import com.example.gwclx.CustomJiaJian; import com.example.gwclx.R; import com.nostra13.universalimageloader.core.ImageLoader; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; /** * Created by Administrator on 2018/1/7 0007. */ public class RecyAdapter extends RecyclerView.Adapter<RecyAdapter.MyViewHolder>{ Context context; //创建大的集合 private List<CartBean.DataBean.ListBean> list; //存放商家的id和商家的名称的map集合 private Map<String,String> map = new HashMap<>(); public RecyAdapter(Context context) { this.context = context; } /** * 添加数据并更新显示 * */ public void add(CartBean cartBean){ //传进来的是bean对象 if(list == null){ list = new ArrayList<>(); } //第一层遍历商家和商品 for (CartBean.DataBean shop : cartBean.getData()){ //把商品的id和商品的名称添加到map集合里 ,,为了之后方便调用 map.put(shop.getSellerid(),shop.getSellerName()); //第二层遍历里面的商品 for (int i=0;i<shop.getList().size();i++){ //添加到list集合里 list.add(shop.getList().get(i)); } } //调用方法 设置显示或隐藏 商铺名 setFirst(list); notifyDataSetChanged(); } /** * 设置数据源,控制是否显示商家 * */ private void setFirst(List<CartBean.DataBean.ListBean> list) { if(list.size()>0){ //如果是第一条数据就设置isFirst为1 list.get(0).setIsFirst(1); //从第二条开始遍历 for (int i=1;i<list.size();i++){ //如果和前一个商品是同一家商店的 if (list.get(i).getSellerid() == list.get(i-1).getSellerid()){ //设置成2不显示商铺 list.get(i).setIsFirst(2); }else{//设置成1显示商铺 list.get(i).setIsFirst(1); //如果当前条目选中,把当前的商铺也选中 if (list.get(i).isItem_check()==true){ list.get(i).setShop_check(list.get(i).isItem_check()); } } } } } @Override public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view = View.inflate(context,R.layout.item,null); MyViewHolder myViewHolder = new MyViewHolder(view); return myViewHolder; } @Override public void onBindViewHolder(final MyViewHolder holder, final int position) { /** * 设置商铺的 shop_checkbox和商铺的名字 显示或隐藏 * */ if(list.get(position).getIsFirst()==1){ //显示商家 holder.shop_checkbox.setVisibility(View.VISIBLE); holder.shop_name.setVisibility(View.VISIBLE); //设置shop_checkbox的选中状态 holder.shop_checkbox.setChecked(list.get(position).isShop_check()); holder.shop_name.setText(map.get(String.valueOf(list.get(position).getSellerid()))); }else{//2 //隐藏商家 holder.shop_name.setVisibility(View.GONE); holder.shop_checkbox.setVisibility(View.GONE); } //拆分images字段 String[] split = list.get(position).getImages().split("\\|"); //设置商品的图片 ImageLoader.getInstance().displayImage(split[0],holder.item_face); //控制商品的item_checkbox,,根据字段改变 holder.item_checkbox.setChecked(list.get(position).isItem_check()); holder.item_name.setText(list.get(position).getTitle()); holder.item_price.setText(list.get(position).getPrice()+""); //调用customjiajian里面的方法设置 加减号中间的数字 holder.customJiaJian.setEditText(list.get(position).getNum()); //商铺的shop_checkbox点击事件 ,控制商品的item_checkbox holder.shop_checkbox.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //先改变数据源中的shop_check list.get(position).setShop_check(holder.shop_checkbox.isChecked()); for (int i=0;i<list.size();i++){ //如果是同一家商铺的 都给成相同状态 if(list.get(position).getSellerid()==list.get(i).getSellerid()){ //当前条目的选中状态 设置成 当前商铺的选中状态 list.get(i).setItem_check(holder.shop_checkbox.isChecked()); } } //刷新适配器 notifyDataSetChanged(); //调用求和的方法 sum(list); } }); //商品的item_checkbox点击事件,控制商铺的shop_checkbox holder.item_checkbox.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //先改变数据源中的item_checkbox list.get(position).setItem_check(holder.item_checkbox.isChecked()); //反向控制商铺的shop_checkbox for (int i=0;i<list.size();i++){ for (int j=0;j<list.size();j++){ //如果两个商品是同一家店铺的 并且 这两个商品的item_checkbox选中状态不一样 if(list.get(i).getSellerid()==list.get(j).getSellerid()&&!list.get(j).isItem_check()){ //就把商铺的shop_checkbox改成false list.get(i).setShop_check(false); break; }else{ //同一家商铺的商品 选中状态都一样,就把商铺shop_checkbox状态改成true list.get(i).setShop_check(true); } } } //更新适配器 notifyDataSetChanged(); //调用求和的方法 sum(list); } }); //删除条目的点击事件 holder.item_delete.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { list.remove(position);//移除集合中的当前数据 //删除完当前的条目 重新判断商铺的显示隐藏 setFirst(list); //调用重新求和 sum(list); notifyDataSetChanged(); } }); //加减号的监听, holder.customJiaJian.setCustomListener(new CustomJiaJian.CustomListener() { @Override public void jiajian(int count) { //改变数据源中的数量 list.get(position).setNum(count); notifyDataSetChanged(); sum(list); } @Override //输入值 求总价 public void shuRuZhi(int count) { list.get(position).setNum(count); notifyDataSetChanged(); sum(list); } }); } /** * 计算总价的方法 * */ private void sum(List<CartBean.DataBean.ListBean> list){ int totalNum = 0;//初始的总价为0 float totalMoney = 0.0f; boolean allCheck = true; for (int i=0;i<list.size();i++){ //把 已经选中的 条目 计算价格 if (list.get(i).isItem_check()){ totalNum += list.get(i).getNum(); totalMoney += list.get(i).getNum()*list.get(i).getPrice(); }else{ //如果有个未选中,就标记为false allCheck = false; } } //接口回调出去 把总价 总数量 和allcheck 传给view层 updateListener.setTotal(totalMoney+"",totalNum+"",allCheck); } //view层调用这个方法, 点击quanxuan按钮的操作 public void quanXuan(boolean checked) { for (int i=0;i<list.size();i++){ list.get(i).setShop_check(checked); list.get(i).setItem_check(checked); } notifyDataSetChanged(); sum(list); } @Override public int getItemCount() { return list==null?0:list.size(); } public static class MyViewHolder extends RecyclerView.ViewHolder { private final CheckBox shop_checkbox; private final TextView shop_name; private final CheckBox item_checkbox; private final TextView item_name; private final TextView item_price; private final CustomJiaJian customJiaJian; private final ImageView item_delete; private final ImageView item_face; public MyViewHolder(View itemView) { super(itemView); shop_checkbox = (CheckBox) itemView.findViewById(R.id.shop_checkbox); shop_name = (TextView) itemView.findViewById(R.id.shop_name); item_checkbox = (CheckBox) itemView.findViewById(R.id.item_checkbox); item_name = (TextView) itemView.findViewById(R.id.item_name); item_price = (TextView) itemView.findViewById(R.id.item_price); customJiaJian = (CustomJiaJian) itemView.findViewById(R.id.custom_jiajian); item_delete = (ImageView) itemView.findViewById(R.id.item_delete); item_face = (ImageView) itemView.findViewById(R.id.item_face); } } UpdateListener updateListener; public void setUpdateListener(UpdateListener updateListener){ this.updateListener = updateListener; } //接口 public interface UpdateListener{ public void setTotal(String total,String num,boolean allCheck); } }///
两个MVP用的接口
ModelCallBack ViewCallBack
package com.example.gwclx.callBack; import com.example.gwclx.CartBean; /** * Created by Administrator on 2018/1/7 0007. */ public interface ModelCallBack { public void success(CartBean cartBean); public void failure(Exception e); }//
package com.example.gwclx.callBack; import com.example.gwclx.CartBean; /** * Created by Administrator on 2018/1/7 0007. */ public interface ViewCallBack { public void success(CartBean cartBean); public void failure(Exception e); }
model层 可以改变接口网址 (拦截器也要改) MyModel
package com.example.gwclx.model; import android.util.Log; import com.example.gwclx.CartBean; import com.example.gwclx.callBack.ModelCallBack; import com.example.gwclx.utils.AbstractUiCallBack; import com.example.gwclx.utils.OkhttpUtils; /** * Created by Administrator on 2018/1/7 0007. */ public class MyModel { public void getData(final ModelCallBack modelCallBack){ //访问接口 String path = "http://120.27.23.105/product/getCarts?uid=3406"; OkhttpUtils.getInstance().asy(null, path, new AbstractUiCallBack<CartBean>() { @Override public void success(CartBean cartBean) { modelCallBack.success(cartBean); Log.d("zzz","成功"+cartBean.toString()); } @Override public void fail(Exception e) { modelCallBack.failure(e); Log.d("zzz","失败"+e.toString()); } }); } }/
Presenter层 MyPresenter
package com.example.gwclx.presenter; import com.example.gwclx.CartBean; import com.example.gwclx.callBack.ModelCallBack; import com.example.gwclx.callBack.ViewCallBack; import com.example.gwclx.model.MyModel; /** * Created by Administrator on 2018/1/7 0007. */ public class MyPresenter { MyModel myModel = new MyModel(); ViewCallBack viewCallBack; public MyPresenter(ViewCallBack viewCallBack) { this.viewCallBack = viewCallBack; } //调用model 层的请求数据 public void getData(){ myModel.getData(new ModelCallBack() { @Override public void success(CartBean cartBean) { if(viewCallBack!=null) { viewCallBack.success(cartBean); } } @Override public void failure(Exception e) { if(viewCallBack!=null) { viewCallBack.failure(e); } } }); } /** * 防止内存泄露 * */ public void detach(){ viewCallBack=null; } } 请求网络的工具类
AbstractUiCallBack
package com.example.gwclx.utils; import android.os.Handler; import android.os.Looper; import com.google.gson.Gson; import java.io.IOException; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import okhttp3.Call; import okhttp3.Response; import okhttp3.Callback; /** * Created by Administrator on 2018/1/7 0007. */ public abstract class AbstractUiCallBack <T> implements Callback { public abstract void success(T t); public abstract void fail(Exception e); private Handler handler = null; private Class clazz; public AbstractUiCallBack(){ handler = new Handler(Looper.getMainLooper()); Type type = getClass().getGenericSuperclass(); Type[] arr = ((ParameterizedType)type).getActualTypeArguments(); clazz = (Class) arr[0]; } @Override public void onFailure(Call call, IOException e) { fail(e); } @Override public void onResponse(Call call, Response response) throws IOException { try { String result = response.body().string(); Gson gson = new Gson(); final T t = (T) gson.fromJson(result,clazz); handler.post(new Runnable() { @Override public void run() { success(t);//成功的回调出去 } }); }catch (Exception e){ e.printStackTrace(); fail(e);//失败的回调 } } }
MyInterceptor
package com.example.gwclx.utils; import java.io.IOException; import okhttp3.Interceptor; import okhttp3.Request; import okhttp3.Response; /** * Created by Administrator on 2018/1/7 0007. */ public class MyInterceptor implements Interceptor { @Override public Response intercept(Chain chain) throws IOException { Request request = chain.request(); //&source=android这个是get带参数 //?source=android 这个是只能get不带传参,还有就是post String url = request.url().toString()+"&source=android"; Request request1 = request.newBuilder().url(url).build(); Response response = chain.proceed(request1); return response; } }///
OkhttpUtils
package com.example.gwclx.utils; import java.util.Map; import java.util.concurrent.TimeUnit; import okhttp3.FormBody; import okhttp3.OkHttpClient; import okhttp3.Request; /** * Created by Administrator on 2018/1/7 0007. */ public class OkhttpUtils { private static OkhttpUtils okhttpUtils = null; private OkhttpUtils(){ } public static OkHttpClient client; public static OkhttpUtils getInstance(){ if(okhttpUtils==null){ okhttpUtils = new OkhttpUtils(); client = new OkHttpClient.Builder() .readTimeout(20, TimeUnit.SECONDS) .writeTimeout(20,TimeUnit.SECONDS) .connectTimeout(20, TimeUnit.SECONDS) .addInterceptor(new MyInterceptor()) .build(); } return okhttpUtils; } public void asy(Map<String,String> params, String url, AbstractUiCallBack callBack){ Request request = null; if(params!=null){ FormBody.Builder builder = new FormBody.Builder(); for(Map.Entry<String,String> entry : params.entrySet()){ builder.add(entry.getKey(),entry.getValue()); } FormBody body = builder.build(); request = new Request.Builder() .url(url) .post(body) .build(); }else{ request = new Request.Builder() .url(url) .build(); } client.newCall(request).enqueue(callBack); } }