Android 购物车页面和逻辑实现

来源:互联网 发布:网络对传统文化的影响 编辑:程序博客网 时间:2024/06/03 20:18

距离上次写第一篇博客已经好久了,今天正好有时间就来写一篇关于最近在做的项目中的一个功能 购物车! 我这个购物车业务逻辑还算可以吧,不算太难,但由于我是第一次做,所以也碰到了很多细节上的问题...所以我想总结下来,方便以后学习和使用..好了先看看效果吧!



目前我做的功能除了结算就这些了...

下面开始来看代码

Activity界面是这样的


首先是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的布局



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();    }}

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

1.

问题:当我单选一个一个选中后,全选按钮也会自动选中 ,但是当我取消一个item后 全选按钮没有自动取消 (正常是只有有一个item没有选中 全选按钮是不会选中的)

解决:首先解决问题要找到原因所在 ,造成这个Bug的原因是我CheckBox的点击事件用的是setOnCheckedChangeListener 后来换成了setOnClickListener 就好了 .

两者都能实现对CheckBox的状态改变的监听,但一般情况下,用的更多的是setOnCheckedChangeListener。因为,当CheckBox的状态不是通过点击事件改变,而是通过其他的方式改变时,比如setCheck(),setOnClickListener无法完成此种情况下的监听。OnCheckChangedListener监听CheckBox的状态,无论来自你的onClick事件还是其他。

2.

问题: 就是在改变物品个数的是时候会出现复用!

解决: 原因就是我没有保存当前 改变后是值, 保存一下就OK了..


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



Demo在这里----->http://download.csdn.net/detail/u011011744/9706870





6 0
原创粉丝点击