美文网首页Android UI交互Android技术知识
Android 购物车页面和逻辑实现

Android 购物车页面和逻辑实现

作者: 一只正在路上的程序员 | 来源:发表于2017-09-19 17:35 被阅读296次

    之前在CSDN上写了几篇..现在想在简书上也写写,所以就过来试试....嘻嘻嘻~~~好,,进入正题....

    这是之前在做的项目中的一个功能 购物车! 我这个购物车业务逻辑还算可以吧,不算太难,但由于我是第一次做,所以也碰到了很多细节上的问题...所以我想总结下来,方便以后学习和使用..好了先看看效果吧!


    20161209152143632.gif

    目前我做的功能除了结算就这些了...
    下面开始来看代码
    Activity界面是这样的


    image.png
    首先是Activity 布局xml
    <?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:orientation="vertical">  
      
        <include  
            android:id="@+id/shopping_title"  
            layout="@layout/layout_title" />  
      
        <TextView  
            android:id="@+id/tv_edit"  
            android:layout_width="wrap_content"  
            android:layout_height="25dp"  
            android:layout_gravity="right"  
            android:layout_margin="10dp"  
            android:text="编辑"  
            android:textSize="18dp" />  
      
      
        <View  
            android:layout_width="match_parent"  
            android:layout_height="1dp"  
            android:layout_below="@id/tv_edit"  
            android:background="@color/gray3" />  
      
      
        <ListView  
            android:id="@+id/list_shopping_cart"  
            android:layout_width="match_parent"  
            android:layout_height="0dp"  
            android:layout_below="@id/tv_edit"  
            android:layout_weight="1"  
            android:scrollbars="none" />  
      
        <View  
            android:layout_width="match_parent"  
            android:layout_height="1dp"  
            android:background="@color/gray3" />  
      
        <RelativeLayout  
            android:id="@+id/rl_bottom"  
            android:layout_width="match_parent"  
            android:layout_height="50dp"  
            android:layout_alignParentBottom="true"  
            android:background="@color/white">  
      
      
            <CheckBox  
            android:id="@+id/ck_all"  
            android:layout_width="wrap_content"  
            android:layout_height="match_parent"  
            android:layout_centerVertical="true"  
            android:button="@drawable/check_box_style"  
            android:checkMark="?android:attr/listChoiceIndicatorMultiple"  
            android:gravity="center"  
            android:paddingLeft="10dp"  
            android:scaleX="0.6"  
            android:scaleY="0.6"  
            android:text="全选"  
            android:textAppearance="?android:attr/textAppearanceLarge"  
            android:textColor="@color/desccolor" />  
      
            <TextView  
                android:id="@+id/tv_settlement"  
                android:layout_width="80dp"  
                android:layout_height="match_parent"  
                android:layout_alignParentRight="true"  
                android:background="@color/desccolor"  
                android:gravity="center"  
                android:text="结算(0)"  
                android:textColor="@color/white" />  
      
            <TextView  
                android:id="@+id/tv_show_price"  
                android:layout_width="wrap_content"  
                android:layout_height="match_parent"  
                android:layout_toLeftOf="@id/tv_settlement"  
                android:gravity="center"  
                android:padding="5dp"  
                android:text="合计:0.00"  
                android:textColor="@color/desccolor" />  
        </RelativeLayout>  
    </LinearLayout>  
    

    再来看 ListView item的布局


    image.png

    item 布局xml

    <?xml version="1.0" encoding="utf-8"?>  
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
        android:layout_width="match_parent"  
        android:layout_height="190dp"  
        android:orientation="vertical">  
      
        <CheckBox  
            android:id="@+id/ck_chose"  
            android:layout_width="wrap_content"  
            android:layout_height="wrap_content"  
            android:layout_centerVertical="true"  
            android:layout_marginLeft="8dp"  
            android:button="@drawable/check_box_style"  
            android:scaleX="0.6"  
            android:scaleY="0.6" />  
      
        <ImageView  
            android:id="@+id/iv_show_pic"  
            android:layout_width="wrap_content"  
            android:layout_height="wrap_content"  
            android:layout_centerVertical="true"  
            android:layout_marginLeft="10dp"  
            android:layout_toRightOf="@id/ck_chose"  
            android:background="@mipmap/demo" />  
      
        <LinearLayout  
            android:layout_width="wrap_content"  
            android:layout_height="wrap_content"  
            android:layout_marginLeft="15dp"  
            android:layout_marginTop="30dp"  
            android:layout_toRightOf="@id/iv_show_pic"  
            android:orientation="vertical">  
      
            <TextView  
                android:id="@+id/tv_commodity_name"  
                android:layout_width="wrap_content"  
                android:layout_height="wrap_content"  
      
                android:text="酒红色纯红色纯羊毛西服套装"  
                android:textColor="@color/black"  
                android:textStyle="bold" />  
      
            <RelativeLayout  
                android:id="@+id/rl_edit"  
                android:layout_width="110dp"  
                android:layout_height="30dp"  
                android:orientation="horizontal"  
                android:visibility="gone">  
      
                <ImageView  
                    android:id="@+id/iv_sub"  
                    android:layout_width="wrap_content"  
                    android:layout_height="wrap_content"  
                    android:background="@mipmap/iv_sub" />  
      
                <TextView  
                    android:id="@+id/tv_show_num"  
                    android:layout_width="wrap_content"  
                    android:layout_height="wrap_content"  
                    android:layout_centerHorizontal="true"  
                    android:layout_centerVertical="true"  
                    android:text="1"  
                    android:textColor="@color/desccolor" />  
      
                <ImageView  
                    android:id="@+id/iv_add"  
                    android:layout_width="wrap_content"  
                    android:layout_height="wrap_content"  
                    android:layout_alignParentRight="true"  
                    android:background="@mipmap/iv_add" />  
      
                <View  
                    android:layout_width="match_parent"  
                    android:layout_height="0.7dp"  
                    android:layout_alignParentBottom="true"  
                    android:background="@color/black" />  
            </RelativeLayout>  
      
      
            <TextView  
                android:id="@+id/tv_fabric"  
                android:layout_width="wrap_content"  
                android:layout_height="wrap_content"  
                android:layout_marginTop="10dp"  
                android:text="面料:"  
                android:textColor="@color/gray5" />  
      
            <LinearLayout  
                android:layout_width="wrap_content"  
                android:layout_height="wrap_content"  
                android:orientation="horizontal">  
      
                <TextView  
                    android:id="@+id/tv_dress"  
                    android:layout_width="wrap_content"  
                    android:layout_height="wrap_content"  
                    android:layout_marginTop="10dp"  
                    android:text="西服尺寸: 48"  
                    android:textColor="@color/gray5" />  
      
            </LinearLayout>  
      
      
            <TextView  
                android:id="@+id/tv_pants"  
                android:layout_width="wrap_content"  
                android:layout_height="wrap_content"  
                android:layout_marginTop="10dp"  
                android:text="西裤尺寸: 68"  
                android:textColor="@color/gray5" />  
      
            <LinearLayout  
                android:layout_width="wrap_content"  
                android:layout_height="wrap_content"  
                android:layout_marginTop="10dp"  
                android:orientation="horizontal">  
      
                <TextView  
                    android:id="@+id/tv_price"  
                    android:layout_width="wrap_content"  
                    android:layout_height="wrap_content"  
                    android:text="¥390"  
                    android:textColor="@color/black"  
                    android:textStyle="bold" />  
      
      
                <TextView  
                    android:id="@+id/tv_num"  
                    android:layout_width="wrap_content"  
                    android:layout_height="wrap_content"  
                    android:layout_marginLeft="40dp"  
                    android:text="x1"  
                    android:textColor="@color/gray5" />  
            </LinearLayout>  
        </LinearLayout>  
      
        <TextView  
            android:id="@+id/tv_delete"  
            android:layout_width="60dp"  
            android:layout_height="match_parent"  
            android:layout_alignParentRight="true"  
            android:background="@color/address_press"  
            android:gravity="center"  
            android:text="删除"  
            android:visibility="gone" />  
      
    </RelativeLayout>  
    

    好了 ,,布局就说完了 现在我们来看看逻辑部分
    由于很多操作是在Activity中操作 ListView的item ,所以我这里选择的是接口回调,我感觉方便些..也许你会有更好的方法.
    首先我们在 Adapter中定义了几个

    /** 
     * 复选框接口 
     */  
    public interface CheckInterface {  
        /** 
         * 组选框状态改变触发的事件 
         * 
         * @param position  元素位置 
         * @param isChecked 元素选中与否 
         */  
        void checkGroup(int position, boolean isChecked);  
    }  
      
      
    /** 
     * 改变数量的接口 
     */  
    public interface ModifyCountInterface {  
        /** 
         * 增加操作 
         * 
         * @param position      组元素位置 
         * @param showCountView 用于展示变化后数量的View 
         * @param isChecked     子元素选中与否 
         */  
        void doIncrease(int position, View showCountView, boolean isChecked);  
      
        /** 
         * 删减操作 
         * 
         * @param position      组元素位置 
         * @param showCountView 用于展示变化后数量的View 
         * @param isChecked     子元素选中与否 
         */  
        void doDecrease(int position, View showCountView, boolean isChecked);  
      
        /** 
         * 删除子item 
         * 
         * @param position 
         */  
        void childDelete(int position);  
    }  
    

    再来看看Adapter 没啥可说的.. 注释我在代码写的还算详细 ,相信能看懂

    public class ShoppingCartAdapter extends BaseAdapter {  
      
        private boolean isShow = true;//是否显示编辑/完成  
        private List<ShoppingCartBean> shoppingCartBeanList;  
        private CheckInterface checkInterface;  
        private ModifyCountInterface modifyCountInterface;  
        private Context context;  
      
        public ShoppingCartAdapter(Context context) {  
            this.context = context;  
        }  
      
        public void setShoppingCartBeanList(List<ShoppingCartBean> shoppingCartBeanList) {  
            this.shoppingCartBeanList = shoppingCartBeanList;  
            notifyDataSetChanged();  
        }  
      
        /** 
         * 单选接口 
         * 
         * @param checkInterface 
         */  
        public void setCheckInterface(CheckInterface checkInterface) {  
            this.checkInterface = checkInterface;  
        }  
      
        /** 
         * 改变商品数量接口 
         * 
         * @param modifyCountInterface 
         */  
        public void setModifyCountInterface(ModifyCountInterface modifyCountInterface) {  
            this.modifyCountInterface = modifyCountInterface;  
        }  
      
        @Override  
        public int getCount() {  
            return shoppingCartBeanList == null ? 0 : shoppingCartBeanList.size();  
        }  
      
        @Override  
        public Object getItem(int position) {  
            return shoppingCartBeanList.get(position);  
        }  
      
        @Override  
        public long getItemId(int position) {  
            return position;  
        }  
      
      
        /** 
         * 是否显示可编辑 
         * 
         * @param flag 
         */  
        public void isShow(boolean flag) {  
            isShow = flag;  
            notifyDataSetChanged();  
        }  
      
        @Override  
        public View getView(final int position, View convertView, ViewGroup parent) {  
      
            final ViewHolder holder;  
            if (convertView == null) {  
                convertView = LayoutInflater.from(context).inflate(R.layout.item_shopping_cart_layout, parent, false);  
                holder = new ViewHolder(convertView);  
                convertView.setTag(holder);  
            } else {  
                holder = (ViewHolder) convertView.getTag();  
            }  
            final ShoppingCartBean shoppingCartBean = shoppingCartBeanList.get(position);  
            holder.tv_commodity_name.setText(shoppingCartBean.getShoppingName());  
            holder.tv_fabric.setText("面料:" + shoppingCartBean.getFabric());  
            holder.tv_dress.setText("西服尺寸:" + shoppingCartBean.getDressSize());  
            holder.tv_pants.setText("西裤尺寸:" + shoppingCartBean.getPantsSize());  
            holder.tv_price.setText("¥:" + shoppingCartBean.getPrice());  
            holder.ck_chose.setChecked(shoppingCartBean.isChoosed());  
            holder.tv_show_num.setText(shoppingCartBean.getCount() + "");  
            holder.tv_num.setText("X" + shoppingCartBean.getCount());  
      
            //单选框按钮  
            holder.ck_chose.setOnClickListener(  
                    new View.OnClickListener() {  
                        @Override  
                        public void onClick(View v) {  
                            shoppingCartBean.setChoosed(((CheckBox) v).isChecked());  
                            checkInterface.checkGroup(position, ((CheckBox) v).isChecked());//向外暴露接口  
                        }  
                    }  
            );  
      
            //增加按钮  
            holder.iv_add.setOnClickListener(new View.OnClickListener() {  
                @Override  
                public void onClick(View v) {  
                    modifyCountInterface.doIncrease(position, holder.tv_show_num, holder.ck_chose.isChecked());//暴露增加接口  
                }  
            });  
      
            //删减按钮  
            holder.iv_sub.setOnClickListener(new View.OnClickListener() {  
                @Override  
                public void onClick(View v) {  
                    modifyCountInterface.doDecrease(position, holder.tv_show_num, holder.ck_chose.isChecked());//暴露删减接口  
                }  
            });  
      
      
            //删除弹窗  
            holder.tv_delete.setOnClickListener(new View.OnClickListener() {  
                @Override  
                public void onClick(View v) {  
                    AlertDialog alert = new AlertDialog.Builder(context).create();  
                    alert.setTitle("操作提示");  
                    alert.setMessage("您确定要将这些商品从购物车中移除吗?");  
                    alert.setButton(DialogInterface.BUTTON_NEGATIVE, "取消",  
                            new DialogInterface.OnClickListener() {  
                                @Override  
                                public void onClick(DialogInterface dialog, int which) {  
                                    return;  
                                }  
                            });  
                    alert.setButton(DialogInterface.BUTTON_POSITIVE, "确定",  
                            new DialogInterface.OnClickListener() {  
                                @Override  
                                public void onClick(DialogInterface dialog, int which) {  
                                    modifyCountInterface.childDelete(position);//删除 目前只是从item中移除  
      
                                }  
                            });  
                    alert.show();  
                }  
            });  
      
            //判断是否在编辑状态下  
            if (isShow) {  
                holder.tv_commodity_name.setVisibility(View.VISIBLE);  
                holder.tv_fabric.setVisibility(View.VISIBLE);  
                holder.rl_edit.setVisibility(View.GONE);  
                holder.tv_delete.setVisibility(View.GONE);  
            } else {  
                holder.tv_commodity_name.setVisibility(View.GONE);  
                holder.tv_fabric.setVisibility(View.GONE);  
                holder.rl_edit.setVisibility(View.VISIBLE);  
                holder.tv_delete.setVisibility(View.VISIBLE);  
            }  
      
            return convertView;  
        }  
      
      
        //初始化控件  
        class ViewHolder {  
            ImageView iv_chose;  
            ImageView iv_show_pic, iv_sub, iv_add;  
            TextView tv_commodity_name, tv_fabric, tv_dress, tv_pants, tv_price, tv_num, tv_delete, tv_show_num;  
            CheckBox ck_chose;  
            RelativeLayout rl_edit;  
      
            public ViewHolder(View itemView) {  
                ck_chose = (CheckBox) itemView.findViewById(R.id.ck_chose);  
                iv_show_pic = (ImageView) itemView.findViewById(R.id.iv_show_pic);  
                iv_sub = (ImageView) itemView.findViewById(R.id.iv_sub);  
                iv_add = (ImageView) itemView.findViewById(R.id.iv_add);  
      
                tv_commodity_name = (TextView) itemView.findViewById(R.id.tv_commodity_name);  
                tv_fabric = (TextView) itemView.findViewById(R.id.tv_fabric);  
                tv_dress = (TextView) itemView.findViewById(R.id.tv_dress);  
                tv_pants = (TextView) itemView.findViewById(R.id.tv_pants);  
                tv_price = (TextView) itemView.findViewById(R.id.tv_price);  
                tv_num = (TextView) itemView.findViewById(R.id.tv_num);  
                tv_delete = (TextView) itemView.findViewById(R.id.tv_delete);  
                tv_show_num = (TextView) itemView.findViewById(R.id.tv_show_num);  
                rl_edit = (RelativeLayout) itemView.findViewById(R.id.rl_edit);  
      
            }  
      
        }
    

    现在我们在来看看Activity 代码, 同样注释写的很详细

    public class ShoppingCartActivity extends BaseActivity implements View.OnClickListener  
            , ShoppingCartAdapter.CheckInterface, ShoppingCartAdapter.ModifyCountInterface {  
        public TextView tv_title, tv_settlement, tv_show_price;  
        private TextView tv_all_check;  
        private CheckBox ck_all;  
        private ListView list_shopping_cart;  
        private ShoppingCartAdapter shoppingCartAdapter;  
        private TextView tv_edit;  
        private boolean flag = false;  
        private List<ShoppingCartBean> shoppingCartBeanList = new ArrayList<>();  
        private boolean mSelect;  
        private double totalPrice = 0.00;// 购买的商品总价  
        private int totalCount = 0;// 购买的商品总数量  
        /** 
         * 批量模式下,用来记录当前选中状态 
         */  
        private SparseArray<Boolean> mSelectState = new SparseArray<Boolean>();  
      
      
        @Override  
        protected int getLayout() {  
            return R.layout.layout_shopping_cart_activity;  
        }  
      
        @Override  
        protected void initView() {  
            tv_title = bindView(R.id.tv_title);  
            tv_title.setText("购物车");  
            list_shopping_cart = bindView(R.id.list_shopping_cart);  
    //        list_shopping_cart.setOnItemClickListener(this);  
            ck_all = bindView(R.id.ck_all);  
            ck_all.setOnClickListener(this);  
    //        ck_all.setOnCheckedChangeListener(this);  
            tv_show_price = bindView(R.id.tv_show_price);  
            tv_settlement = bindView(R.id.tv_settlement);  
            tv_settlement.setOnClickListener(this);  
            tv_edit = bindView(R.id.tv_edit);  
            tv_edit.setOnClickListener(this);  
            shoppingCartAdapter = new ShoppingCartAdapter(this);  
            shoppingCartAdapter.setCheckInterface(this);  
            shoppingCartAdapter.setModifyCountInterface(this);  
            list_shopping_cart.setAdapter(shoppingCartAdapter);  
            shoppingCartAdapter.setShoppingCartBeanList(shoppingCartBeanList);  
      
        }  
      
        @Override  
        protected void initData() {  
      
            for (int i = 0; i < 6; i++) {  
                ShoppingCartBean shoppingCartBean = new ShoppingCartBean();  
                shoppingCartBean.setShoppingName("高端大气上档次的T桖");  
                shoppingCartBean.setFabric("纯棉");  
                shoppingCartBean.setDressSize(48);  
                shoppingCartBean.setPantsSize(65);  
                shoppingCartBean.setPrice(60);  
                shoppingCartBean.setCount(2);  
                shoppingCartBeanList.add(shoppingCartBean);  
            }  
      
        }  
      
        @Override  
        public void onClick(View v) {  
            switch (v.getId()) {  
                //全选按钮    
                case R.id.ck_all:  
                    if (shoppingCartBeanList.size() != 0) {  
                        if (ck_all.isChecked()) {  
                            for (int i = 0; i < shoppingCartBeanList.size(); i++) {  
                                shoppingCartBeanList.get(i).setChoosed(true);  
                            }  
                            shoppingCartAdapter.notifyDataSetChanged();  
                        } else {  
                            for (int i = 0; i < shoppingCartBeanList.size(); i++) {  
                                shoppingCartBeanList.get(i).setChoosed(false);  
                            }  
                            shoppingCartAdapter.notifyDataSetChanged();  
                        }  
                    }  
                    statistics();  
                    break;  
                case R.id.tv_edit:  
                    flag = !flag;  
                    if (flag) {  
                        tv_edit.setText("完成");  
                        shoppingCartAdapter.isShow(false);  
                    } else {  
                        tv_edit.setText("编辑");  
                        shoppingCartAdapter.isShow(true);  
                    }  
                    break;  
            }  
        }  
      
        /** 
         * 单选 
         * 
         * @param position  组元素位置 
         * @param isChecked 组元素选中与否 
         */  
        @Override  
        public void checkGroup(int position, boolean isChecked) {  
      
            shoppingCartBeanList.get(position).setChoosed(isChecked);  
      
            if (isAllCheck())  
                ck_all.setChecked(true);  
            else  
                ck_all.setChecked(false);  
      
            shoppingCartAdapter.notifyDataSetChanged();  
            statistics();  
        }  
      
      
        /** 
         * 遍历list集合 
         * 
         * @return 
         */  
        private boolean isAllCheck() {  
      
            for (ShoppingCartBean group : shoppingCartBeanList) {  
                if (!group.isChoosed())  
                    return false;  
            }  
            return true;  
        }  
      
        /** 
         * 统计操作 
         * 1.先清空全局计数器<br> 
         * 2.遍历所有子元素,只要是被选中状态的,就进行相关的计算操作 
         * 3.给底部的textView进行数据填充 
         */  
        public void statistics() {  
            totalCount = 0;  
            totalPrice = 0.00;  
            for (int i = 0; i < shoppingCartBeanList.size(); i++) {  
                ShoppingCartBean shoppingCartBean = shoppingCartBeanList.get(i);  
                if (shoppingCartBean.isChoosed()) {  
                    totalCount++;  
                    totalPrice += shoppingCartBean.getPrice() * shoppingCartBean.getCount();  
                }  
            }  
            tv_show_price.setText("合计:" + totalPrice);  
            tv_settlement.setText("结算(" + totalCount + ")");  
        }  
      
        /** 
         * 增加 
         * 
         * @param position      组元素位置 
         * @param showCountView 用于展示变化后数量的View 
         * @param isChecked     子元素选中与否 
         */  
        @Override  
        public void doIncrease(int position, View showCountView, boolean isChecked) {  
            ShoppingCartBean shoppingCartBean = shoppingCartBeanList.get(position);  
            int currentCount = shoppingCartBean.getCount();  
            currentCount++;  
            shoppingCartBean.setCount(currentCount);  
            ((TextView) showCountView).setText(currentCount + "");  
            shoppingCartAdapter.notifyDataSetChanged();  
            statistics();  
        }  
      
        /** 
         * 删减 
         * 
         * @param position      组元素位置 
         * @param showCountView 用于展示变化后数量的View 
         * @param isChecked     子元素选中与否 
         */  
        @Override  
        public void doDecrease(int position, View showCountView, boolean isChecked) {  
            ShoppingCartBean shoppingCartBean = shoppingCartBeanList.get(position);  
            int currentCount = shoppingCartBean.getCount();  
            if (currentCount == 1) {  
                return;  
            }  
            currentCount--;  
            shoppingCartBean.setCount(currentCount);  
            ((TextView) showCountView).setText(currentCount + "");  
            shoppingCartAdapter.notifyDataSetChanged();  
            statistics();  
      
        }  
      
        /** 
         * 删除 
         * 
         * @param position 
         */  
        @Override  
        public void childDelete(int position) {  
            shoppingCartBeanList.remove(position);  
            shoppingCartAdapter.notifyDataSetChanged();  
            statistics();  
      
        }  
      
    }  
    

    整体的就是这样,,我说一下 我做的时候遇到的问题和解决办法

    问题:当我单选一个一个选中后,全选按钮也会自动选中 ,但是当我取消一个item后 全选按钮没有自动取消 (正常是只有有一个item没有选中 全选按钮是不会选中的)
    解决:首先解决问题要找到原因所在 ,造成这个Bug的原因是我CheckBox的点击事件用的是setOnCheckedChangeListener 后来换成了setOnClickListener 就好了 .
    两者都能实现对CheckBox的状态改变的监听,但一般情况下,用的更多的是setOnCheckedChangeListener。因为,当CheckBox的状态不是通过点击事件改变,而是通过其他的方式改变时,比如setCheck(),setOnClickListener无法完成此种情况下的监听。OnCheckChangedListener监听CheckBox的状态,无论来自你的onClick事件还是其他。

    问题: 就是在改变物品个数的是时候会出现复用!
    解决: 原因就是我没有保存当前 改变后是值, 保存一下就OK了..

    总体上就是这些了.......感兴趣的同学可以下载demo看看

    Demo在这里----->https://github.com/HelloSinger/ShoppingCat
    (第一次在github上上传项目,还不是很熟悉项目展示有点问题,不过不影响下载,我之后再改改)

    相关文章

      网友评论

      本文标题:Android 购物车页面和逻辑实现

      本文链接:https://www.haomeiwen.com/subject/hfhgsxtx.html