Android----仿京东购物车(二级列表,mvp请求数据)


下面是购物车列表的简单实现

android中常常要用到ListView,有时也要用到ExpandableListView,如在手机设置中,对于分类有很好的效果,会用ListView的人一定会用ExpandableListView,因为
 ExpandableListView extends ListView的,下面来看个简单的例子
 
 运行效果图:


  1. 一、布局

           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);
        }
    }
     
阅读更多

没有更多推荐了,返回首页