Android实现淘宝购物车

来源:互联网 发布:php医院预约挂号源码 编辑:程序博客网 时间:2024/04/27 22:44

先上效果:
这里写图片描述

购物车实现使用的ExpandableListView,关于它的使用的就不在多说,网上的资料都非常多。
xml里面布局代码:

<?xml version="1.0" encoding="utf-8"?><LinearLayout 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"    android:orientation="vertical"    tools:context="com.xp.shoppingcart.MainActivity">    <include layout="@layout/include_toolbar" />    <ExpandableListView        android:id="@+id/expandableListView"        android:layout_width="match_parent"        android:layout_height="0dp"        android:layout_weight="1"        android:scrollbars="none"        android:divider="@null"/>    <View        android:layout_width="match_parent"        android:layout_height="1dp"        android:background="@color/divide_line"/>    <LinearLayout        android:layout_width="match_parent"        android:layout_height="49dp"        android:background="@android:color/white"        android:gravity="center_vertical"        android:orientation="horizontal">        <com.xp.shoppingcart.SmoothCheckBox            android:id="@+id/cb_select_all"            android:layout_width="24dp"            android:layout_height="24dp"            android:layout_marginLeft="15dp" />        <TextView            android:layout_width="0dp"            android:layout_height="wrap_content"            android:layout_marginLeft="5dp"            android:layout_weight="0.69"            android:text="全选"            android:textColor="#333333"            android:textSize="15sp" />        <LinearLayout            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:gravity="end"            android:orientation="vertical">            <LinearLayout                android:layout_width="wrap_content"                android:layout_height="wrap_content">                <TextView                    android:layout_width="wrap_content"                    android:layout_height="wrap_content"                    android:text="合计"                    android:textColor="#333333"                    android:textSize="15sp" />                <TextView                    android:id="@+id/tv_all_money"                    android:layout_width="wrap_content"                    android:layout_height="wrap_content"                    android:text="¥0"                    android:textColor="#FE3824"                    android:textSize="15sp" />            </LinearLayout>            <TextView                android:id="@+id/tv_transport"                android:layout_width="wrap_content"                android:layout_height="wrap_content"                android:text="运费:¥0"                android:textColor="#999999"                android:textSize="11sp" />        </LinearLayout>        <Button            android:id="@+id/btn_settlement"            android:layout_width="95dp"            android:layout_height="match_parent"            android:layout_marginLeft="15dp"            android:background="#FE3824"            android:text="结算(0)"            android:textColor="@android:color/white"            android:textSize="16sp" />    </LinearLayout></LinearLayout>

初始化控件:

private void initView() {        mExpandableListView = (ExpandableListView) findViewById(R.id.expandableListView);        mCbSelectAll = (SmoothCheckBox) findViewById(R.id.cb_select_all);        mTvAllMoney = (TextView) findViewById(R.id.tv_all_money);        mBtnBuy = (Button) findViewById(R.id.btn_settlement);        //去掉ExpandableListView 默认的箭头        mExpandableListView.setGroupIndicator(null);        //用于列表滑动时,EditText清除焦点,收起软键盘        mExpandableListView.setOnScrollListener(new AbsListView.OnScrollListener() {            @Override            public void onScrollStateChanged(AbsListView absListView, int scrollState) {                if (SCROLL_STATE_TOUCH_SCROLL == scrollState) {                    InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Activity                            .INPUT_METHOD_SERVICE);                    View focusView = getCurrentFocus();                    if (focusView != null) {                        inputMethodManager.hideSoftInputFromWindow(focusView.getWindowToken(), InputMethodManager                                .HIDE_NOT_ALWAYS);                        focusView.clearFocus();                    }                }            }            @Override            public void onScroll(AbsListView absListView, int i, int i1, int i2) {            }        });    }

数据的话都是自己造的数据,存放在assets文件夹里面,下面是模拟网络请求数据并解析

private void initData() {        //读取数据解析        AssetManager assetManager = getAssets();        try {            InputStream is = assetManager.open("data.json");            BufferedReader br = new BufferedReader(new InputStreamReader(is));            stringBuffer = new StringBuffer();            String str;            while ((str = br.readLine()) != null) {                stringBuffer.append(str);            }        } catch (IOException e) {            e.printStackTrace();        }        Gson gson = new Gson();        goodBean = gson.fromJson(stringBuffer.toString(), GoodBean.class);        mAdapter = new ExpandableListAdapter(this, goodBean);        mAdapter.setChangedListener(this);        mExpandableListView.setAdapter(mAdapter);        //展开所有的分组        for (int i = 0; i < goodBean.getContent().size(); i++) {            mExpandableListView.expandGroup(i);        }    }

模拟的json数据里面添加了店铺和商品是否被选中的标志字段,用来存放选中的状态。

适配器里面根据请求数据里面保存的状态设置店铺是否被选中:

@Override    public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {        GroupViewHolder holder;        if (convertView == null) {            convertView = LayoutInflater.from(mContext).inflate(R.layout.item_shopingcart_group, parent, false);            holder = new GroupViewHolder(convertView);            convertView.setTag(holder);        } else {            holder = (GroupViewHolder) convertView.getTag();        }        holder.cbGroupItem.setTag(groupPosition);        holder.cbGroupItem.setOnClickListener(listener);        holder.tvPosition.setText(goodBean.getContent().get(groupPosition).getAddress());        //根据获取的状态设置是否被选中        if (goodBean.getContent().get(groupPosition).isSelected()) {            if (!holder.cbGroupItem.isChecked()) {                holder.cbGroupItem.setChecked(true);            }        } else {            holder.cbGroupItem.setChecked(false);        }        return convertView;    }

头部布局的xml,这里使用了自定义的checkBox,点击选中的时候可以添加动画(具体代码看源码):

<?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="wrap_content"    android:background="@android:color/white"    android:orientation="vertical">    <View        android:layout_width="match_parent"        android:layout_height="3dp"        android:background="@color/divide_line" />    <LinearLayout        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:gravity="center_vertical"        android:padding="15dp">        <com.xp.shoppingcart.SmoothCheckBox            android:id="@+id/cb_group_item"            android:layout_width="24dp"            android:layout_height="24dp" />        <TextView            android:id="@+id/tv_position"            android:layout_width="0dp"            android:layout_height="wrap_content"            android:layout_marginLeft="15dp"            android:layout_weight="1"            android:drawableLeft="@mipmap/ic_position"            android:drawablePadding="3dp"            android:text="京东旗舰店发货"            android:textColor="#333333"            android:textSize="15sp" />    </LinearLayout></LinearLayout>

根据请求数据里面保存的状态设置店铺是否被选中:

@Override    public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {        ChildViewHolder holder;        if (convertView == null) {            convertView = LayoutInflater.from(mContext).inflate(R.layout.item_shopingcart_child, parent, false);            holder = new ChildViewHolder(convertView);            convertView.setTag(holder);        } else {            holder = (ChildViewHolder) convertView.getTag();        }        String tag = groupPosition + "," + childPosition;        holder.cbItem.setTag(tag);        holder.tvReduce.setTag(tag);        holder.tvAdd.setTag(tag);        holder.imgDelete.setTag(tag);        holder.imgIcon.setTag(tag);        holder.cbItem.setOnClickListener(listener);        holder.tvReduce.setOnClickListener(listener);        //添加商品数量        holder.tvAdd.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View view) {                String tag = view.getTag().toString();                String[] split;                int groupId = 0;                int childId = 0;                int allCount = goodBean.getAllCount();                int allMoney;                if (tag.contains(",")) {                    split = tag.split(",");                    groupId = Integer.parseInt(split[0]);                    childId = Integer.parseInt(split[1]);                }                String goodCount = goodBean.getContent().get(groupId).getGoodDetail().get(childId).getCount();                goodBean.getContent().get(groupId).getGoodDetail().get(childId).setCount(addCount(goodCount));                allMoney = goodBean.getAllMoney();                if (goodBean.getContent().get(groupId).getGoodDetail().get(childId).isSelected()) {                    allMoney += Integer.valueOf(goodBean.getContent().get(groupId).getGoodDetail().get(childId).getPrice());                    updateViewListener.update(goodBean.isAllSelect(), allCount, allMoney);                }                goodBean.setAllMoney(allMoney);                notifyDataSetChanged();            }        });        holder.imgDelete.setOnClickListener(listener);        //根据获取的状态设置是否被选中        if (goodBean.getContent().get(groupPosition).getGoodDetail().get(childPosition).isSelected()) {            holder.cbItem.setChecked(true);        } else {            holder.cbItem.setChecked(false);        }        //设置数据        holder.tvPrice.setText("¥" + goodBean.getContent().get(groupPosition).getGoodDetail().get(childPosition).getPrice());        holder.tvGoodName.setText(goodBean.getContent().get(groupPosition).getGoodDetail().get(childPosition).getName());        //对商品数量的监听        EditTextWatcher textWatcher = (EditTextWatcher) holder.etCount.getTag(KEY_DATA);        if (textWatcher != null) {            holder.etCount.removeTextChangedListener(textWatcher);        }        holder.etCount.setText(String.valueOf(goodBean.getContent().get(groupPosition).getGoodDetail().get(childPosition).getCount()));        EditTextWatcher watcher = new EditTextWatcher(goodBean.getContent().get(groupPosition).getGoodDetail().get(childPosition));        holder.etCount.setTag(KEY_DATA, watcher);        holder.etCount.addTextChangedListener(watcher);        holder.etCount.setText(goodBean.getContent().get(groupPosition).getGoodDetail().get(childPosition).getCount());        return convertView;    }

每个商品的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="wrap_content"    android:background="@android:color/white"    android:orientation="horizontal"    android:paddingBottom="15dp"    android:paddingRight="15dp">    <LinearLayout        android:id="@+id/ll_check"        android:layout_width="wrap_content"        android:layout_height="match_parent"        android:gravity="center"        android:paddingLeft="15dp"        android:paddingRight="17dp">        <com.xp.shoppingcart.SmoothCheckBox            android:id="@+id/cb_item"            android:layout_width="24dp"            android:layout_height="24dp"            android:layout_gravity="center_vertical" />    </LinearLayout>    <LinearLayout        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:orientation="vertical">        <View            android:layout_width="match_parent"            android:layout_height="1dp"            android:background="@color/divide_line" />        <LinearLayout            android:layout_width="match_parent"            android:layout_height="wrap_content"            android:layout_marginTop="15dp"            android:orientation="horizontal">            <ImageView                android:id="@+id/img_icon"                android:layout_width="78dp"                android:layout_height="78dp"                android:src="@mipmap/ic_phone" />            <RelativeLayout                android:layout_width="0dp"                android:layout_height="match_parent"                android:layout_marginLeft="15dp"                android:layout_marginTop="8dp"                android:layout_weight="1">                <TextView                    android:id="@+id/tv_good_name"                    android:layout_width="wrap_content"                    android:layout_height="wrap_content"                    android:text="" />                <TextView                    android:id="@+id/tv_reduce"                    android:layout_width="30dp"                    android:layout_height="30dp"                    android:layout_below="@id/tv_good_name"                    android:layout_marginTop="6dp"                    android:background="@drawable/selector_shopping_cart_subtract"                    android:gravity="center"                    android:text="-"                    android:textColor="@color/text_666666"                    android:textSize="15sp" />                <EditText                    android:id="@+id/et_count"                    android:layout_width="49dp"                    android:layout_height="30dp"                    android:layout_alignTop="@+id/tv_reduce"                    android:layout_marginBottom="1dp"                    android:layout_toRightOf="@+id/tv_reduce"                    android:background="@drawable/bg_input_box"                    android:gravity="center"                    android:inputType="number"                    android:maxLength="6"                    android:text="1"                    android:textColor="@color/text_666666"                    android:textCursorDrawable="@null"                    android:textSize="12sp" />                <TextView                    android:id="@+id/tv_add"                    android:layout_width="30dp"                    android:layout_height="30dp"                    android:layout_alignTop="@+id/tv_reduce"                    android:layout_toRightOf="@id/et_count"                    android:background="@drawable/selector_shopping_cart_add"                    android:gravity="center"                    android:text="+"                    android:textColor="@color/text_666666"                    android:textSize="15sp" />                <TextView                    android:id="@+id/tv_price"                    android:layout_width="wrap_content"                    android:layout_height="wrap_content"                    android:layout_alignParentBottom="true"                    android:layout_alignParentLeft="true"                    android:layout_alignParentStart="true"                    android:text="¥899"                    android:textColor="#FE3824"                    android:textSize="13sp" />            </RelativeLayout>            <LinearLayout                android:layout_width="wrap_content"                android:layout_height="wrap_content"                android:layout_marginLeft="18dp"                android:gravity="end"                android:orientation="vertical">            </LinearLayout>            <ImageView                android:id="@+id/img_delete"                android:layout_width="wrap_content"                android:layout_height="wrap_content"                android:layout_gravity="center_vertical"                android:layout_marginTop="5dp"                android:src="@mipmap/icon_delete" />        </LinearLayout>    </LinearLayout></LinearLayout>

这里是对店铺点击选中事件的处理:

case R.id.cb_group_item:                    checkBox = (SmoothCheckBox) v;                    //根据父checkbox的选中状态设置存储数据里面商品是否被选中                    goodBean.getContent().get(groupPosition).setIsSelected(!checkBox.isChecked());                    if (!checkBox.isChecked()) {                        for (int i = 0; i < childSize; i++) {                            if (!goodBean.getContent().get(groupPosition).getGoodDetail().get(i).isSelected()) {                                allCount++;                                goodBean.getContent().get(groupPosition).getGoodDetail().get(i).setIsSelected(!checkBox.isChecked());                                allMoney += Integer.valueOf(goodBean.getContent().get(groupPosition).getGoodDetail().get(i).getCount())                                        * Integer.valueOf(goodBean.getContent().get(groupPosition).getGoodDetail().get(i).getPrice());                            }                        }                    } else {                        allCount -= childSize;                        for (int i = 0; i < childSize; i++) {                            goodBean.getContent().get(groupPosition).getGoodDetail().get(i).setIsSelected(!checkBox.isChecked());                            allMoney -= Integer.valueOf(goodBean.getContent().get(groupPosition).getGoodDetail().get(i).getCount())                                    * Integer.valueOf(goodBean.getContent().get(groupPosition).getGoodDetail().get(i).getPrice());                        }                    }                    //父item选中的数量                    int fCount = 0;                    //判断是否所有的父item都被选中,决定全选按钮状态                    for (int i = 0; i < goodBean.getContent().size(); i++) {                        if (goodBean.getContent().get(i).isSelected()) {                            fCount++;                        }                    }                    if (fCount == goodBean.getContent().size()) {                        goodBean.setAllSelect(true);                    } else {                        goodBean.setAllSelect(false);                    }                    goodBean.setAllCount(allCount);                    goodBean.setAllMoney(allMoney);                    notifyDataSetChanged();                    updateViewListener.update(goodBean.isAllSelect(), allCount, allMoney);                    break;

接下来是对每个商品选中的处理:

case R.id.cb_item:                    checkBox = (SmoothCheckBox) v;                    int cCount = 0;//子item被选中的数量                    int fcCount = 0;//父item被选中的数量                    goodBean.getContent().get(groupId).getGoodDetail().get(childId).setIsSelected(!checkBox.isChecked());                    //遍历父item所有数据,统计被选中的item数量                    for (int i = 0; i < goodBean.getContent().get(groupId).getGoodDetail().size(); i++) {                        if (goodBean.getContent().get(groupId).getGoodDetail().get(i).isSelected()) {                            cCount++;                        }                    }                    //判断是否所有的子item都被选中,决定父item状态                    if (cCount == goodBean.getContent().get(groupId).getGoodDetail().size()) {                        goodBean.getContent().get(groupId).setIsSelected(true);                    } else {                        goodBean.getContent().get(groupId).setIsSelected(false);                    }                    //判断是否所有的父item都被选中,决定全选按钮状态                    for (int i = 0; i < goodBean.getContent().size(); i++) {                        if (goodBean.getContent().get(i).isSelected()) {                            fcCount++;                        }                    }                    if (fcCount == goodBean.getContent().size()) {                        goodBean.setAllSelect(true);                    } else {                        goodBean.setAllSelect(false);                    }                    //判断子item状态,更新结算总商品数和合计Money                    if (!checkBox.isChecked()) {                        allCount++;                        allMoney += Integer.valueOf(goodBean.getContent().get(groupId).getGoodDetail().get(childId).getCount())                                * Integer.valueOf(goodBean.getContent().get(groupId).getGoodDetail().get(childId).getPrice());                    } else {                        allCount--;                        allMoney -= Integer.valueOf(goodBean.getContent().get(groupId).getGoodDetail().get(childId).getCount())                                * Integer.valueOf(goodBean.getContent().get(groupId).getGoodDetail().get(childId).getPrice());                    }                    goodBean.setAllCount(allCount);                    goodBean.setAllMoney(allMoney);                    notifyDataSetChanged();                    updateViewListener.update(goodBean.isAllSelect(), allCount, allMoney);                    break;

自定义回调接口更新显示的价格、数量:

/** * 更新数据的回调接口 */public interface UpdateView {    void update(boolean isAllSelected, int count, int price);}

在主界面实现回调接口,更新数据:

@Override    public void update(boolean isAllSelected, int count, int price) {        mBtnBuy.setText("结算(" + count + ")");        mTvAllMoney.setText("¥" + price);        mCbSelectAll.setChecked(isAllSelected);    }

下载完整代码点击下边
源码Demo

原创粉丝点击