Android--购物车的实现详解

         现在做商城的越来越多,或者说添加商城功能的应用越来越多,昨天有人给我要购物车的Demo,所以本篇文章主要总结一下商城中购物车部分的实现过程和具体代码,整体实现虽然不难,但要注意它的逻辑关系,我使用的是本地数据,界面不是那么美观,大家就将就看一下主要的实现方式。

先看一下Activity的布局(我这使用的是Listview,写项目的话建议大家使用Recyclerview):

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.huo_nolice.shopcar.MainActivity">

    <Button
        android:id="@+id/bt_main_mode"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="切换模式"
        android:onClick="onClick"/>
    <ListView
        android:id="@+id/lv_main_list"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@id/bt_main_mode">
    </ListView>
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="60dp"
        android:layout_alignParentBottom="true"
        android:background="#00f"
        android:alpha="0.5">
        <CheckBox
            android:id="@+id/cb_main_checkAll"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="15dp"
            android:layout_centerVertical="true"/>
        <TextView
            android:id="@+id/tv_main_count"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerVertical="true"
            android:layout_marginLeft="15dp"
            android:layout_toRightOf="@id/cb_main_checkAll"
            android:text="000"
            android:textSize="25sp"
            android:textColor="#f00"/>
        <Button
            android:id="@+id/bt_main_pay"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:layout_centerVertical="true"
            android:text="去结算"/>
    </RelativeLayout>
</RelativeLayout>
布局没什么好说的之后是Listview中item的布局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:gravity="center_vertical"
    >
    <CheckBox
        android:id="@+id/cb_item_check"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="15dp"/>

    <RelativeLayout
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1">
        <ImageView
            android:id="@+id/iv_item_icon"
            android:layout_width="80dp"
            android:layout_height="80dp"
            android:layout_centerVertical="true"
            android:src="@mipmap/ic_launcher"/>
        <TextView
            android:id="@+id/tv_item_info"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_toRightOf="@id/iv_item_icon"
            android:layout_marginLeft="10dp"
            android:layout_marginTop="15dp"
            android:text="info"
            android:maxLines="1"
            />
        <TextView
            android:id="@+id/tv_item_price"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@id/tv_item_info"
            android:layout_toRightOf="@id/iv_item_icon"
            android:layout_marginLeft="20dp"
            android:layout_marginTop="20dp"
            android:text="price"/>
        <Button
            android:id="@+id/bt_item_add"
            android:layout_width="40dp"
            android:layout_height="40dp"
            android:layout_alignParentBottom="true"
            android:layout_alignParentRight="true"
            android:layout_marginBottom="10dp"
            android:layout_marginRight="10dp"
            android:text="+"/>
        <TextView
            android:id="@+id/tv_item_count"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignBaseline="@id/bt_item_add"
            android:layout_alignParentBottom="true"
            android:layout_marginRight="10dp"
            android:layout_toLeftOf="@id/bt_item_add"
            android:paddingBottom="10dp"
            android:text="0"/>
        <Button
            android:id="@+id/bt_item_subtract"
            android:layout_width="40dp"
            android:layout_height="40dp"
            android:layout_alignParentBottom="true"
            android:layout_marginBottom="10dp"
            android:layout_marginRight="10dp"
            android:layout_toLeftOf="@id/tv_item_count"
            android:text="-"/>
    </RelativeLayout>
    <Button
        android:id="@+id/bt_item_delete"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:layout_marginRight="15dp"
        android:text="x"/>
</LinearLayout>
需要为listview添加adapter,下边是我项目的adapter写法可能与平常你们的写法不同,只是个人习惯而已,在adapter中我做了 注释,可以根据注释理解。

public class ShopCarAdapter extends BaseAdapter{
    private Context mContext;
    private List<ShopInfo>mInfos;
    private boolean mMode;
    private View.OnClickListener mOnClickListener;
    private CompoundButton.OnCheckedChangeListener mChangeListener;
    public ShopCarAdapter (List<ShopInfo>infos,Context context){
        mContext=context;
        mInfos=infos;
        mChangeListener= (CompoundButton.OnCheckedChangeListener) mContext;
        mOnClickListener= (View.OnClickListener) mContext;
    }

    @Override
    public int getCount() {
        return mInfos==null?0:mInfos.size();
    }

    @Override
    public Object getItem(int i) {
        return mInfos.get(i);
    }

    @Override
    public long getItemId(int i) {
        return i;
    }

    @Override
    public View getView(int i, View view, ViewGroup viewGroup) {
        ViewHolder holder=null;
        if(view==null) {
            view= LayoutInflater.from(mContext).inflate(R.layout.item_shopcar,null);
            holder=new ViewHolder(view);
            view.setTag(holder);
        }else {
            holder= (ViewHolder) view.getTag();
        }
        holder.mTextViewInfo.setText(mInfos.get(i).info);
        holder.mTextViewPrice.setText(mInfos.get(i).price+"");
        holder.mTextViewCount.setText(mInfos.get(i).count+"");
        //设置删除按钮的可见和不可见
        if(mMode) {
            holder.mButtonDelete.setVisibility(View.VISIBLE);
            holder.mButtonDelete.setEnabled(true);
        }else {
            holder.mButtonDelete.setVisibility(View.GONE);
        }
        //给CheckBox设置选中的监听事件
        holder.mCheckBox.setOnCheckedChangeListener(mChangeListener);
        holder.mCheckBox.setTag(i);
        //设置CheckBox的选中状态
        holder.mCheckBox.setChecked(mInfos.get(i).isCheck);

        //给添加和减少按钮设置点击事件
        holder.mButtonAdd.setOnClickListener(mOnClickListener);
        holder.mButtonSub.setOnClickListener(mOnClickListener);
        //关联button位置
        holder.mButtonAdd.setTag(i);
        holder.mButtonSub.setTag(i);
        //给删除按钮设置点击事件
        holder.mButtonDelete.setOnClickListener(mOnClickListener);
        holder.mButtonDelete.setTag(i);
        Picasso.with(mContext).load(mInfos.get(i).icon).into(holder.mImageViewIcon);
        return view;
    }

    public static class ViewHolder{
        private TextView mTextViewInfo,mTextViewCount,mTextViewPrice;
        private ImageView mImageViewIcon;
        private CheckBox mCheckBox;
        private Button mButtonAdd,mButtonSub,mButtonDelete;
        public ViewHolder(View itemView){
            mTextViewInfo= (TextView) itemView.findViewById(R.id.tv_item_info );
            mTextViewCount= (TextView) itemView.findViewById(R.id.tv_item_count);
            mTextViewPrice= (TextView) itemView.findViewById(R.id.tv_item_price);
            mImageViewIcon= (ImageView) itemView.findViewById(R.id.iv_item_icon);
            mCheckBox= (CheckBox) itemView.findViewById(R.id.cb_item_check);
            mButtonAdd= (Button) itemView.findViewById(R.id.bt_item_add);
            mButtonSub= (Button) itemView.findViewById(R.id.bt_item_subtract);
            mButtonDelete= (Button) itemView.findViewById(R.id.bt_item_delete);
        }
    }
    //以下两个方法会在Activity中调用
    public void setModel(boolean mode){
        mMode=mode;
        notifyDataSetChanged();
    }
    public int getMoney(){
        int money=0;
        if(mInfos==null||mInfos.size()==0){
            return money;
        }
        for (int i = 0; i <mInfos.size() ; i++) {
            ShopInfo info=mInfos.get(i);
            if(info.isCheck){
                int itemMoney=info.count*info.price;
                money+=itemMoney;
            }
        }
        return money;
    }

}
最后就是Activity的部分了,我之所以把Activity放在最后了是因为我把Listview的item中的控件的点击事件在Adapter中做了关联,而监听的实现过程放在了Activity中更方便处理数据。

public class MainActivity extends AppCompatActivity implements CompoundButton.OnCheckedChangeListener, View.OnClickListener {

    private ListView mListView;
    private List<ShopInfo>mData;
    private CheckBox mCheckBox;
    private Button mButtonMode;
    private TextView mTextViewMoney;
    private ShopCarAdapter mAdapter;
    private boolean mMode;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
        initData();
        setData();
        setListener();
    }

    private void setListener() {
        mCheckBox.setOnCheckedChangeListener(this);
        mButtonMode.setOnClickListener(this);
    }

    private void setData() {
        mListView.setAdapter(mAdapter);
    }

    private void initData() {
        //初始化数据 自己模拟的数据
        mData=new ArrayList<>();
        for (int i = 0; i <30 ; i++) {
            ShopInfo info=new ShopInfo();
            info.count=i+1;
            info.price=(i+1)*2;
            info.icon="https://ss2.bdstatic.com/70cFvnSh_Q1YnxGkpoWK1HF6hhy/it/u=1265160970,3356031848&fm=23&gp=0.jpg";
            if(i%3==0) {
                info.info="亚马逊";
            }else if(i%3==1) {
                info.info="京东";
            }else{
                info.info="天猫";
            }
            mData.add(info);
        }
        // 初始化adapter
         mAdapter=new ShopCarAdapter(mData,this);
        //给adapter设置一个数据改变的监听
        mAdapter.registerDataSetObserver(new DataSetObserver() {
            //当调用adapter的notofiedDataChange的时候就会调用这个方法
            @Override
            public void onChanged() {
                super.onChanged();
                int money=mAdapter.getMoney();
                mTextViewMoney.setText(money+"");
            }
        });

    }

    private void initView() {
        getSupportActionBar().hide();
        mListView= (ListView) findViewById(R.id.lv_main_list);
        mCheckBox= (CheckBox) findViewById(R.id.cb_main_checkAll);
        mButtonMode= (Button) findViewById(R.id.bt_main_mode);
        mTextViewMoney= (TextView) findViewById(R.id.tv_main_count);
    }

    @Override
    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
        switch(buttonView.getId()){
            case R.id.cb_main_checkAll:
                for (int i = 0; i <mData.size(); i++) {
                    mData.get(i).isCheck=isChecked;
                }
                mAdapter.notifyDataSetChanged();
                break;
            case R.id.cb_item_check:
                //获取与item中CheckBox关联的位置
               Integer position= (Integer) buttonView.getTag();
                if(position!=null){
                    mData.get(position).isCheck=isChecked;
                    mAdapter.notifyDataSetChanged();
                }
                break;
        }

    }

    @Override
    public void onClick(View v) {
        Integer postion= (Integer) v.getTag();
        if(v!=null){
            switch(v.getId()){
                case R.id.bt_main_mode:
                    mMode=!mMode;
                    mAdapter.setModel(mMode);
                    //上边两句与下边的实现结果是一样的,只是写法不同
//                    if(mMode){
//                        mAdapter.setModel(false);
//                        mMode=false;
//                    }else{
//                        mAdapter.setModel(true);
//                        mMode=true;
//                    }
                    break;
                case R.id.bt_item_add:
                    if(postion!=null){
                        mData.get(postion).count++;
                        mAdapter.notifyDataSetChanged();
                    }
                    break;
                case R.id.bt_item_subtract:
                    if(postion!=null){
                        mData.get(postion).count--;
                        if(mData.get(postion).count<=0){
                            mData.get(postion).count=0;
                        }
                        mAdapter.notifyDataSetChanged();
                    }
                    break;
                case R.id.bt_item_delete:
                    if(postion!=null){
                        mData.remove((int)postion);
                        mAdapter.notifyDataSetChanged();
                        //或者使用下一种方式实现:
//                        ShopInfo info=mData.get(postion);
//                        mData.remove(info);
                    }
                    break;
            }

        }
    }
}
购物车的基本逻辑就完成了,下边看一下最终的实现结果:

   


       源码地址:http://download.csdn.net/detail/huohao_blogs/9858505









  • 3
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值