您的位置:首页 > 移动开发 > Android开发

Android实现淘宝购物车

2017-07-05 17:04 489 查看
先上效果:



购物车实现使用的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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: