现在做商城的越来越多,或者说添加商城功能的应用越来越多,昨天有人给我要购物车的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.youkuaiyun.com/detail/huohao_blogs/9858505