Android实现淘宝购物车

先上效果:
Android实现淘宝购物车_第1张图片

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


<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,点击选中的时候可以添加动画(具体代码看源码):


<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布局:


<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

你可能感兴趣的:(Android开发)