一、布局
MainActivity的布局:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <android.support.v7.widget.RecyclerView android:id="@+id/recyclerview" android:layout_width="match_parent" android:layout_height="385dp" android:layout_weight="0.77"> </android.support.v7.widget.RecyclerView> <LinearLayout android:orientation="horizontal" android:layout_width="wrap_content" android:layout_height="wrap_content"> <CheckBox android:layout_marginLeft="20dp" android:id="@+id/qunxuan_checkbox" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="全选"/> <LinearLayout android:layout_marginLeft="60dp" android:orientation="vertical" android:layout_width="wrap_content" android:layout_height="wrap_content"> <TextView android:id="@+id/zongjia_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="商品的总价:"/> <TextView android:id="@+id/zongshu_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="商品的总数:"/> </LinearLayout> <Button android:layout_marginLeft="60dp" android:id="@+id/jiesuan_butn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="结算"/> </LinearLayout> </LinearLayout>
子条目的布局
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <LinearLayout android:orientation="horizontal" android:layout_width="wrap_content" android:layout_height="wrap_content"> <CheckBox android:id="@+id/shangjia_checkbox" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <TextView android:id="@+id/shangjia_name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="商家的名字"/> </LinearLayout> <LinearLayout android:orientation="horizontal" android:layout_width="wrap_content" android:layout_height="wrap_content"> <CheckBox android:layout_marginLeft="10dp" android:layout_gravity="center_vertical" android:id="@+id/shangpin_checkbox" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <LinearLayout android:layout_marginLeft="20dp" android:orientation="vertical" android:layout_width="wrap_content" android:layout_height="wrap_content"> <ImageView android:id="@+id/item_iamgeview" android:layout_width="50dp" android:layout_height="50dp" android:src="@mipmap/ic_launcher"/> <TextView android:id="@+id/item_name_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="商品的名字"/> <TextView android:id="@+id/item_price_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="商品的价格"/> <com.bawei.shop1122application.CustomView android:id="@+id/customview" android:layout_width="wrap_content" android:layout_height="wrap_content"/> </LinearLayout> <Button android:layout_gravity="center_vertical" android:id="@+id/item_shanchu_butn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="删除"/> </LinearLayout> </LinearLayout>自定义控件
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="match_parent"> <Button android:id="@+id/custom_jian" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="-"/> <EditText android:id="@+id/count_edtext" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="1"/> <Button android:id="@+id/custom_add" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="+"/> </LinearLayout>
二、MVP层
1,M层接口
public interface IModel { //定义请求数据成功的方法和失败的方法 public void success(MyBean myBean); public void failture(Exception e); }2.M层类
public class MyModel { //请求数据的方法 public void getData(final IModel iModel){ //利用封装请求数据,添加泛型 OkhttpUtils.getInstance().asy(null, "http://120.27.23.105/product/getCarts?uid=100", new AbstractUiCallBack<MyBean>() { @Override public void success(MyBean myBean) { //调用接口中的方法 iModel.success(myBean); } @Override public void failure(Exception e) { iModel.failture(e); } }); } }3、P层
public class MyPresenter { //实例model和view private MyModel myModel; private IView iView; //注意下边构造器 public MyPresenter(IView iView) { this.myModel = new MyModel(); this.iView = iView; } public void getData(){ myModel.getData(new IModel() { @Override public void success(MyBean myBean) { if (iView!=null){ iView.success(myBean); } } @Override public void failture(Exception e) { if (iView!=null){ iView.failture(e); } } }); } /** * 防止内存泄漏 */ public void detach(){ iView = null; } }
4、V层接口
public interface IView { //接口里边 //定义请求数据成功的方法和失败的方法 public void success(MyBean myBean); public void failture(Exception e); }
三、适配器
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder>{ //上下文和数据源 Context context; private List<MyBean.DataBean.ListBean> list; // 存放 商家的id 和 商家名称 private Map<String,String> map = new HashMap<>(); public MyAdapter(Context context) { this.context = context; } //控制商家显示的方法 public void setFirst(List<MyBean.DataBean.ListBean> list){ /*bean中添加一个控制显示的属性isFirst, 1为显示,2为影藏 这个商家是否是第一个出现的,如果是就影藏,如果不是就展示*/ if (list.size()>0){ //数据第一个肯定是显示的 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).isShangpincheck()){ list.get(i).setShangjiacheck(list.get(i).isShangpincheck()); } } } } } @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { //创建布局 View view = View.inflate(context,R.layout.item_layout,null); return new ViewHolder(view); } @Override public void onBindViewHolder(final ViewHolder holder, final int position) { //填充值 //设置商家的多选框的状态 if (list.get(position).getIsFirst()==1){ //显示商家和商家名字 holder.shangjia_checkbox.setVisibility(View.VISIBLE); holder.shangjia_name.setVisibility(View.VISIBLE); //既然显示就给填充值,就需要有一个是否选中了这个多选框的属性,去bean添加 holder.shangjia_checkbox.setChecked(list.get(position).isShangjiacheck()); //设置商家的名字 holder.shangjia_name.setText(map.get(String.valueOf(list.get(position).getSellerid()))); }else{ //隐藏商家和商家名 holder.shangjia_checkbox.setVisibility(View.GONE); holder.shangjia_name.setVisibility(View.GONE); } //设置商品的多选框的状态 holder.shangpin_checkbox.setChecked(list.get(position).isShangpincheck()); //填充图片时,要拆分 String str[] = list.get(position).getImages().split("\\|"); ImageLoader.getInstance().displayImage(str[0],holder.item_iamgeview);//二参为控件 //填充价格 holder.item_price_text.setText(list.get(position).getPrice()+""); //填充商品名称 holder.item_name_text.setText(list.get(position).getTitle()); //填充自定义控件中输入框的值 holder.customview.setEditText(list.get(position).getNum()); //删除的点击事件 holder.item_shanchu_butn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { list.remove(position); //删除以后显示第一个 list.remove(position); setFirst(list); notifyDataSetChanged(); sum(list); } }); //加减号的点击事件 holder.customview.setJiaJian(new CustomView.JiaJian() { @Override public void dianji(int count) { //取到当前的数量 list.get(position).setNum(count); notifyDataSetChanged(); sum(list); } }); //商家的多选框框点击事件 holder.shangjia_checkbox.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { //商家的点击填充值 list.get(position).setShangjiacheck(holder.shangjia_checkbox.isChecked()); //遍历 for (int i=0;i<list.size();i++){ //如果当前的状态id和数据中的相对应,就说明选中了,商品也要选中 if (list.get(position).getSellerid()==list.get(i).getSellerid()){ list.get(i).setShangpincheck(holder.shangjia_checkbox.isChecked()); } } notifyDataSetChanged(); sum(list); } }); //商品的多选框点击事件 holder.shangpin_checkbox.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { //商品的点击填充值 list.get(position).setShangpincheck(holder.shangpin_checkbox.isChecked()); //遍历 for (int i=0;i<list.size();i++){ for (int j=0;j<list.size();j++){ //如果当前的状态id和数据中的相对应,并且不等于当前商品的点击状态 if(list.get(i).getSellerid() == list.get(j).getSellerid() && !list.get(j).isShangpincheck()){ //没有选中 list.get(i).setShangjiacheck(false); break; }else { //选中 list.get(i).setShangjiacheck(true); } } } notifyDataSetChanged(); sum(list); } }); } //计算总价的方法, public void sum(List<MyBean.DataBean.ListBean> list){ int zongshu = 0; float zongjia = 0.0f; boolean allcheck = true; //循环计算 for (int i = 0;i<list.size();i++){ //如果有选中的商品,就计算 if (list.get(i).isShangpincheck()){ zongshu += list.get(i).getNum(); zongjia += list.get(i).getNum()*list.get(i).getPrice(); }else{ allcheck = false; } } //接口对象调用方法暴露数据 updataUi.gengxin(zongjia+"",zongshu+"",allcheck); } //全选的方法 public void selectAll(boolean check){ for(int i=0;i<list.size();i++){ //赋值的 list.get(i).setShangjiacheck(check); list.get(i).setShangpincheck(check); } notifyDataSetChanged(); sum(list); } @Override public int getItemCount() { return list==null?0:list.size(); } //把请求到的数据添加到集合中,并跟新 public void addData(MyBean myBean) { //如果集合是空的,就要先new出集合 if (list==null){ list = new ArrayList<>(); } //集合不为空的话,就要,添加到集合中 //便利商家,shangjia商家对象 for (MyBean.DataBean shangjia:myBean.getData()){ map.put(shangjia.getSellerid(),shangjia.getSellerName()); //便利出商品 for (int i=0;i<shangjia.getList().size();i++){ this.list.add(shangjia.getList().get(i)); } } //添加到view刚进去要显示 setFirst(this.list); //刷新数据 notifyDataSetChanged(); } public class ViewHolder extends RecyclerView.ViewHolder { private final CheckBox shangjia_checkbox; private final TextView shangjia_name; private final CheckBox shangpin_checkbox; private final ImageView item_iamgeview; private final TextView item_name_text; private final TextView item_price_text; private final Button item_shanchu_butn; private final CustomView customview; public ViewHolder(View itemView) { super(itemView); //找到控件 shangjia_checkbox = itemView.findViewById(R.id.shangjia_checkbox); shangjia_name = itemView.findViewById(R.id.shangjia_name); shangpin_checkbox = itemView.findViewById(R.id.shangpin_checkbox); item_iamgeview = itemView.findViewById(R.id.item_iamgeview); item_name_text = itemView.findViewById(R.id.item_name_text); item_price_text = itemView.findViewById(R.id.item_price_text); customview = itemView.findViewById(R.id.customview); item_shanchu_butn = itemView.findViewById(R.id.item_shanchu_butn); } } //更新UI界面的接口,mvp模式,View层不做逻辑。。所以,最后回调给V层 public UpdataUi updataUi; public void setUpdataUi(UpdataUi updataUi) { this.updataUi = updataUi; } public interface UpdataUi{ //需要的参数为,总价格,总数量和是否全选 void gengxin(String zongjia, String zongshu, boolean allcheck); } }
四、Activity
public class MainActivity extends AppCompatActivity implements IView{ private RecyclerView recyclerview; private CheckBox qunxuan_checkbox; private TextView zongjia_text; private TextView zongshu_text; private Button jiesuan_butn; private MyAdapter myAdapter; private LinearLayoutManager manager; private MyPresenter myPresenter; @Override protected void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //找到控件 recyclerview = (RecyclerView) findViewById(R.id.recyclerview); qunxuan_checkbox = (CheckBox) findViewById(R.id.qunxuan_checkbox); zongjia_text = (TextView) findViewById(R.id.zongjia_text); zongshu_text = (TextView) findViewById(R.id.zongshu_text); jiesuan_butn = (Button) findViewById(R.id.jiesuan_butn); //全选 qunxuan_checkbox.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { myAdapter.selectAll(qunxuan_checkbox.isChecked()); } }); //qunxuan_checkbox.setChecked(); //数据.实例化P myPresenter = new MyPresenter(this); myPresenter.getData(); //适配器 myAdapter = new MyAdapter(this); //创建布局管理器 manager = new LinearLayoutManager(this); //设置适配器和布局管理器 recyclerview.setAdapter(myAdapter); recyclerview.setLayoutManager(manager); //回调接口 myAdapter.setUpdataUi(new MyAdapter.UpdataUi() { @Override public void gengxin(String zongjia, String zongshu, boolean allcheck) { qunxuan_checkbox.setChecked(allcheck); zongshu_text.setText(zongshu); zongjia_text.setText(zongjia); } }); } @Override public void success(MyBean myBean) { myAdapter.addData(myBean); } @Override public void failture(Exception e) { } //防止内存泄漏的方法 @Override protected void onDestroy() { super.onDestroy(); //调用P层的方法 myPresenter.detach(); } }
五、需要用到的ok封装和拦截器
1、导入OKhttp封装包
2、添加自定义拦截器
public class LoggingInterceptor implements Interceptor { @Override public Response intercept(Chain chain) throws IOException { Request request = chain.request(); long t1 = System.nanoTime(); // logger.info(String.format("Sending request %s on %s%n%s", // request.url(), chain.connection(), request.headers())); Response response = chain.proceed(request); long t2 = System.nanoTime(); // logger.info(String.format("Received response for %s in %.1fms%n%s", // response.request().url(), (t2 - t1) / 1e6d, response.headers())); System.out.println("t2 = " + (t2-t1)); return response; } }3.bean,数据来源于网络请求
4.使用Imageloard请求图片.注意配置和添加网络请求权限
public class MyApp extends Application{ @Override public void onCreate() { super.onCreate(); ImageLoaderConfiguration configuration = new ImageLoaderConfiguration.Builder(this).build(); ImageLoader.getInstance().init(configuration); } }
六、自定义实现类
public class CustomView extends LinearLayout { private Button custom_jian; private EditText count_edtext; private Button custom_add; //定义输入框的默认值 int mcount = 1; public CustomView(Context context) { super(context); } public CustomView(Context context, AttributeSet attrs) { super(context, attrs); //创建布局 View view = View.inflate(context,R.layout.customview_layout,null); //找到控件 custom_jian = view.findViewById(R.id.custom_jian); count_edtext = view.findViewById(R.id.count_edtext); custom_add = view.findViewById(R.id.custom_add); //减号的点击事件 custom_jian.setOnClickListener(new OnClickListener() { @Override public void onClick(View view) { //点击之前先拿到输入框里的值 String string = count_edtext.getText().toString().trim(); //转化数据类型 int count = Integer.valueOf(string); //如果输入框的数据大于1,点击减号的时候,就让其减少一 if (count>1){ mcount = count-1; count_edtext.setText(mcount+""); } //接口回调 if (jiaJian!=null){ jiaJian.dianji(mcount); } } }); //加号的点击事件 custom_add.setOnClickListener(new OnClickListener() { @Override public void onClick(View view) { //点击之前先拿到输入框里的值 String string = count_edtext.getText().toString().trim(); //转化数据类型 int count = Integer.valueOf(string)+1; //如果输入框的数据大于1,点击减号的时候,就让其减少一 mcount = count; count_edtext.setText(mcount+""); //接口回调 if (jiaJian!=null){ jiaJian.dianji(mcount); } } }); //中间输入框内的变化 count_edtext.addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) { } @Override public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) { } @Override public void afterTextChanged(Editable editable) { } }); addView(view); } //给输入框赋值的方法 public void setEditText(int num){ if(count_edtext != null){ count_edtext.setText(num+""); } } public CustomView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } //加减号的点击事件接口 JiaJian jiaJian; public void setJiaJian(JiaJian jiaJian) { this.jiaJian = jiaJian; } public interface JiaJian{ public void dianji(int count); } }