Android商城购物车页面实现和逻辑实现
16lz
2021-01-23
公司最近的项目有一个商城模块,需要实现购物车的功能,在网上找到一些demo,自己整合完善了一下,现在来看看效果图如何:
购物车界面
image.png
image.png
看到这张图,我想大家对它的布局想必不会陌生,上层是一个Title
image.png
这很容易实现,设置主题为
android:theme="@android:style/Theme.Holo.Light.NoActionBar"
代码就很容易实现了,在主界面中加入
id="@+id/shopping_title" layout="@layout/layout_title" />
layout_title的布局如下
"http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="50dp" android:background="@color/purple_button" android:orientation="vertical">
中间是一个ListView,最底层是一个LinearLayout,其具体实现如下:
id="@+id/rl_bottom" android:layout_width="match_parent" android:layout_height="50dp" android:layout_alignParentBottom="true" android:background="@color/white"> id="@+id/ck_all" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_centerVertical="true" android:button="@drawable/check_box_style" android:checkMark="?android:attr/listChoiceIndicatorMultiple" android:gravity="center" android:paddingLeft="10dp" android:scaleX="0.6" android:scaleY="0.6" android:text="全选" android:textAppearance="?android:attr/textAppearanceLarge" android:textColor="@color/black" /> id="@+id/tv_show_price" android:layout_width="0dp" android:layout_weight="1" android:layout_height="match_parent" android:gravity="center" android:padding="5dp" android:text="合计:0.00" android:textColor="@color/black" /> id="@+id/tv_settlement" android:layout_width="100dp" android:layout_height="match_parent" android:layout_alignParentRight="true" android:background="@color/purple_button" android:gravity="center" android:text="结算(0)" android:textColor="@color/white" />
listView的item_shopping_cart_layout布局如下
<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="100dp" android:orientation="vertical"> <CheckBox android:id="@+id/ck_chose" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerVertical="true" android:layout_marginLeft="5dp" android:button="@drawable/check_box_style" android:scaleX="0.6" android:scaleY="0.6" /> <ImageView android:id="@+id/iv_show_pic" android:layout_width="70dp" android:layout_height="80dp" android:layout_centerVertical="true" android:layout_marginLeft="5dp" android:background="@drawable/demo1" android:layout_toRightOf="@id/ck_chose" /> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="10dp" android:layout_marginTop="15dp" android:layout_toRightOf="@id/iv_show_pic" android:orientation="vertical"> <TextView android:id="@+id/tv_commodity_name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="酒红色纯红色纯羊毛西服套装" android:textColor="@color/black" android:textSize="12sp" android:textStyle="bold" /> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal"> <TextView android:id="@+id/tv_commodity_attr" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="3dp" android:text="属性:粉蓝色" android:textSize="12sp" android:textColor="@color/colorPrimary" /> LinearLayout> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="4dp" android:orientation="horizontal"> <TextView android:id="@+id/tv_commodity_price" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="¥390" android:textColor="@color/red" android:textSize="12sp" android:textStyle="bold" /> <TextView android:id="@+id/tv_commodity_num" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="20dp" android:text="x1" android:textColor="@color/gray" /> <LinearLayout android:id="@+id/rl_edit" android:layout_width="120dp" android:background="@color/qianhui" android:layout_height="30dp" android:layout_marginLeft="20dp" > <TextView android:id="@+id/iv_sub" android:layout_width="0dp" android:layout_weight="1" android:gravity="center" android:textColor="@color/black" android:background="@color/white" android:layout_margin="1dp" android:layout_height="match_parent" android:text=" - " /> <TextView android:id="@+id/tv_commodity_show_num" android:layout_width="0dp" android:layout_weight="1" android:gravity="center" android:background="@color/white" android:layout_margin="1dp" android:layout_height="match_parent" android:text="1" /> <TextView android:id="@+id/iv_add" android:layout_width="0dp" android:layout_weight="1" android:gravity="center" android:background="@color/white" android:layout_margin="1dp" android:layout_height="match_parent" android:text=" + " /> LinearLayout> LinearLayout> LinearLayout> <ImageView android:id="@+id/tv_commodity_delete" android:layout_width="50dp" android:layout_height="40dp" android:layout_alignParentRight="true" android:layout_centerVertical="true" android:background="@drawable/delete" android:gravity="center" android:layout_margin="5dp" android:visibility="gone" />RelativeLayout>
效果图如下
image.png
ListView的适配器具体实现如下:
package com.diandianguanjia.adapter;import android.app.AlertDialog;import android.content.Context;import android.content.DialogInterface;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.AdapterView;import android.widget.BaseAdapter;import android.widget.CheckBox;import android.widget.ImageView;import android.widget.LinearLayout;import android.widget.RelativeLayout;import android.widget.TextView;import com.diandianguanjia.ddhk.R;import com.diandianguanjia.model.ShoppingCartBean;import com.diandianguanjia.util.StringUtil;import com.nostra13.universalimageloader.core.ImageLoader;import java.util.List;/** * Created by AYD on 2016/11/21. * * 购物车Adapter */public class ShoppingCartAdapter extends BaseAdapter { private boolean isShow = true;//是否显示编辑/完成 private List shoppingCartBeanList; private CheckInterface checkInterface; private ModifyCountInterface modifyCountInterface; private Context context; public ShoppingCartAdapter(Context context) { this.context = context; } public void setShoppingCartBeanList(List shoppingCartBeanList) { this.shoppingCartBeanList = shoppingCartBeanList; notifyDataSetChanged(); } /** * 单选接口 * * @param checkInterface */ public void setCheckInterface(CheckInterface checkInterface) { this.checkInterface = checkInterface; } /** * 改变商品数量接口 * * @param modifyCountInterface */ public void setModifyCountInterface(ModifyCountInterface modifyCountInterface) { this.modifyCountInterface = modifyCountInterface; } @Override public int getCount() { return shoppingCartBeanList == null ? 0 : shoppingCartBeanList.size(); } @Override public Object getItem(int position) { return shoppingCartBeanList.get(position); } @Override public long getItemId(int position) { return position; } /** * 是否显示可编辑 * * @param flag */ public void isShow(boolean flag) { isShow = flag; notifyDataSetChanged(); } @Override public View getView(final int position, View convertView, ViewGroup parent) { final ViewHolder holder; if (convertView == null) { convertView = LayoutInflater.from(context).inflate(R.layout.item_shopping_cart_layout, parent, false); holder = new ViewHolder(convertView); convertView.setTag(holder); } else { holder = (ViewHolder) convertView.getTag(); } final ShoppingCartBean shoppingCartBean = shoppingCartBeanList.get(position); boolean choosed = shoppingCartBean.isChoosed(); if (choosed){ holder.ckOneChose.setChecked(true); }else{ holder.ckOneChose.setChecked(false); } String attribute = shoppingCartBean.getAttribute(); if (!StringUtil.isEmpty(attribute)){ holder.tvCommodityAttr.setText(attribute); }else{ holder.tvCommodityAttr.setText(shoppingCartBean.getDressSize()+""); } holder.tvCommodityName.setText(shoppingCartBean.getShoppingName()); holder.tvCommodityPrice.setText(shoppingCartBean.getPrice()+""); holder.tvCommodityNum.setText(" X"+shoppingCartBean.getCount()+""); holder.tvCommodityShowNum.setText(shoppingCartBean.getCount()+""); ImageLoader.getInstance().displayImage(shoppingCartBean.getImageUrl(),holder.ivShowPic); //单选框按钮 holder.ckOneChose.setOnClickListener( new View.OnClickListener() { @Override public void onClick(View v) { shoppingCartBean.setChoosed(((CheckBox) v).isChecked()); checkInterface.checkGroup(position, ((CheckBox) v).isChecked());//向外暴露接口 } } ); //增加按钮 holder.ivAdd.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { modifyCountInterface.doIncrease(position, holder.tvCommodityShowNum, holder.ckOneChose.isChecked());//暴露增加接口 } }); //删减按钮 holder.ivSub.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { modifyCountInterface.doDecrease(position, holder.tvCommodityShowNum, holder.ckOneChose.isChecked());//暴露删减接口 } }); //删除弹窗 holder.tvCommodityDelete.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { AlertDialog alert = new AlertDialog.Builder(context).create(); alert.setTitle("操作提示"); alert.setMessage("您确定要将这些商品从购物车中移除吗?"); alert.setButton(DialogInterface.BUTTON_NEGATIVE, "取消", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { return; } }); alert.setButton(DialogInterface.BUTTON_POSITIVE, "确定", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { modifyCountInterface.childDelete(position);//删除 目前只是从item中移除 } }); alert.show(); } }); //判断是否在编辑状态下 if (isShow) { holder.tvCommodityName.setVisibility(View.VISIBLE); holder.rlEdit.setVisibility(View.GONE); holder.tvCommodityNum.setVisibility(View.VISIBLE); holder.tvCommodityDelete.setVisibility(View.GONE); } else { holder.tvCommodityName.setVisibility(View.VISIBLE); holder.rlEdit.setVisibility(View.VISIBLE); holder.tvCommodityNum.setVisibility(View.GONE); holder.tvCommodityDelete.setVisibility(View.VISIBLE); } return convertView; } //初始化控件 class ViewHolder { ImageView ivShowPic,tvCommodityDelete; TextView tvCommodityName, tvCommodityAttr, tvCommodityPrice, tvCommodityNum, tvCommodityShowNum,ivSub, ivAdd; CheckBox ckOneChose; LinearLayout rlEdit; public ViewHolder(View itemView) { ckOneChose = (CheckBox) itemView.findViewById(R.id.ck_chose); ivShowPic = (ImageView) itemView.findViewById(R.id.iv_show_pic); ivSub = (TextView) itemView.findViewById(R.id.iv_sub); ivAdd = (TextView) itemView.findViewById(R.id.iv_add); tvCommodityName = (TextView) itemView.findViewById(R.id.tv_commodity_name); tvCommodityAttr = (TextView) itemView.findViewById(R.id.tv_commodity_attr); tvCommodityPrice = (TextView) itemView.findViewById(R.id.tv_commodity_price); tvCommodityNum = (TextView) itemView.findViewById(R.id.tv_commodity_num); tvCommodityShowNum = (TextView) itemView.findViewById(R.id.tv_commodity_show_num); tvCommodityDelete = (ImageView) itemView.findViewById(R.id.tv_commodity_delete); rlEdit = (LinearLayout) itemView.findViewById(R.id.rl_edit); } } /** * 复选框接口 */ public interface CheckInterface { /** * 组选框状态改变触发的事件 * * @param position 元素位置 * @param isChecked 元素选中与否 */ void checkGroup(int position, boolean isChecked); } /** * 改变数量的接口 */ public interface ModifyCountInterface { /** * 增加操作 * * @param position 元素位置 * @param showCountView 用于展示变化后数量的View * @param isChecked 子元素选中与否 */ void doIncrease(int position, View showCountView, boolean isChecked); /** * 删减操作 * * @param position 元素位置 * @param showCountView 用于展示变化后数量的View * @param isChecked 子元素选中与否 */ void doDecrease(int position, View showCountView, boolean isChecked); /** * 删除子item * * @param position */ void childDelete(int position); }}
使用接口回调的方法暴露选择复选框和改变数量、删除item的方法
/** * 复选框接口 */ public interface CheckInterface { /** * 组选框状态改变触发的事件 * * @param position 元素位置 * @param isChecked 元素选中与否 */ void checkGroup(int position, boolean isChecked); } /** * 改变数量的接口 */ public interface ModifyCountInterface { /** * 增加操作 * @param position 元素位置 * @param showCountView 用于展示变化后数量的View * @param isChecked 子元素选中与否 */ void doIncrease(int position, View showCountView, boolean isChecked); /** * 删减操作 * @param position 元素位置 * @param showCountView 用于展示变化后数量的View * @param isChecked 子元素选中与否 */ void doDecrease(int position, View showCountView, boolean isChecked); /** * 删除子item * @param position */ void childDelete(int position); }
在购物车主界面中全部代码实现如下:在代码中是使用了xUtils的注解功能来减少findViewId(),其他的功能具体看下面的源码:
/** * Created by an on 2017/6/14. * 购物车界面 * */public class ShoppingCartActivity extends Activity implements View.OnClickListener , ShoppingCartAdapter.CheckInterface, ShoppingCartAdapter.ModifyCountInterface { private static final String TAG = "ShoppingCartActivity"; @ViewInject(R.id.btn_back) Button btnBack; @ViewInject(R.id.ck_all)//全选 CheckBox ckAll; @ViewInject(R.id.tv_show_price)//总额 TextView tvShowPrice; @ViewInject(R.id.tv_settlement)//结算 TextView tvSettlement; @ViewInject(R.id.bt_header_right)//编辑 TextView btnEdit;//tv_edit @ViewInject(R.id.list_shopping_cart) ListView list_shopping_cart; private ShoppingCartAdapter shoppingCartAdapter; private boolean flag = false; private List shoppingCartBeanList = new ArrayList<>(); private boolean mSelect; private double totalPrice = 0.00;// 购买的商品总价 private int totalCount = 0;// 购买的商品总数量 @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.layout_shopping_cart_activity); ViewUtils.inject(this); initView(); initData(); } private void initView() { btnEdit.setText("编辑"); btnEdit.setOnClickListener(this); ckAll.setOnClickListener(this); tvSettlement.setOnClickListener(this); btnBack.setOnClickListener(this); } //初始化数据 protected void initData() { for (int i = 0; i < 2; i++) { ShoppingCartBean shoppingCartBean = new ShoppingCartBean(); shoppingCartBean.setShoppingName("上档次的T桖"); shoppingCartBean.setDressSize(20); shoppingCartBean.setId(i); shoppingCartBean.setPrice(30.6); shoppingCartBean.setCount(1); shoppingCartBean.setImageUrl("https://img.alicdn.com/bao/uploaded/i2/TB1YfERKVXXXXanaFXXXXXXXXXX_!!0-item_pic.jpg_430x430q90.jpg"); shoppingCartBeanList.add(shoppingCartBean); } for (int i = 0; i < 2; i++) { ShoppingCartBean shoppingCartBean = new ShoppingCartBean(); shoppingCartBean.setShoppingName("瑞士正品夜光男女士手表情侣精钢带男表防水石英学生非天王星机械"); shoppingCartBean.setAttribute("黑白色"); shoppingCartBean.setPrice(89); shoppingCartBean.setId(i+2); shoppingCartBean.setCount(3); shoppingCartBean.setImageUrl("https://gd1.alicdn.com/imgextra/i1/2160089910/TB2M_NSbB0kpuFjSsppXXcGTXXa_!!2160089910.jpg"); shoppingCartBeanList.add(shoppingCartBean); } shoppingCartAdapter = new ShoppingCartAdapter(this); shoppingCartAdapter.setCheckInterface(this); shoppingCartAdapter.setModifyCountInterface(this); list_shopping_cart.setAdapter(shoppingCartAdapter); shoppingCartAdapter.setShoppingCartBeanList(shoppingCartBeanList); } @Override public void onClick(View v) { switch (v.getId()) { //全选按钮 case R.id.ck_all: if (shoppingCartBeanList.size() != 0) { if (ckAll.isChecked()) { for (int i = 0; i < shoppingCartBeanList.size(); i++) { shoppingCartBeanList.get(i).setChoosed(true); } shoppingCartAdapter.notifyDataSetChanged(); } else { for (int i = 0; i < shoppingCartBeanList.size(); i++) { shoppingCartBeanList.get(i).setChoosed(false); } shoppingCartAdapter.notifyDataSetChanged(); } } statistics(); break; case R.id.bt_header_right: flag = !flag; if (flag) { btnEdit.setText("完成"); shoppingCartAdapter.isShow(false); } else { btnEdit.setText("编辑"); shoppingCartAdapter.isShow(true); } break; case R.id.tv_settlement: //结算 lementOnder(); break; case R.id.btn_back: finish(); break; } } /** * 结算订单、支付 */ private void lementOnder() { //选中的需要提交的商品清单 for (ShoppingCartBean bean:shoppingCartBeanList ){ boolean choosed = bean.isChoosed(); if (choosed){ String shoppingName = bean.getShoppingName(); int count = bean.getCount(); double price = bean.getPrice(); int size = bean.getDressSize(); String attribute = bean.getAttribute(); int id = bean.getId(); Log.d(TAG,id+"----id---"+shoppingName+"---"+count+"---"+price+"--size----"+size+"--attr---"+attribute); } } ToastUtil.showL(this,"总价:"+totalPrice); //跳转到支付界面 } /** * 单选 * @param position 组元素位置 * @param isChecked 组元素选中与否 */ @Override public void checkGroup(int position, boolean isChecked) { shoppingCartBeanList.get(position).setChoosed(isChecked); if (isAllCheck()) ckAll.setChecked(true); else ckAll.setChecked(false); shoppingCartAdapter.notifyDataSetChanged(); statistics(); } /** * 遍历list集合 * @return */ private boolean isAllCheck() { for (ShoppingCartBean group : shoppingCartBeanList) { if (!group.isChoosed()) return false; } return true; } /** * 统计操作 * 1.先清空全局计数器
* 2.遍历所有子元素,只要是被选中状态的,就进行相关的计算操作 * 3.给底部的textView进行数据填充 */ public void statistics() { totalCount = 0; totalPrice = 0.00; for (int i = 0; i < shoppingCartBeanList.size(); i++) { ShoppingCartBean shoppingCartBean = shoppingCartBeanList.get(i); if (shoppingCartBean.isChoosed()) { totalCount++; totalPrice += shoppingCartBean.getPrice() * shoppingCartBean.getCount(); } } tvShowPrice.setText("合计:" + totalPrice); tvSettlement.setText("结算(" + totalCount + ")"); } /** * 增加 * @param position 组元素位置 * @param showCountView 用于展示变化后数量的View * @param isChecked 子元素选中与否 */ @Override public void doIncrease(int position, View showCountView, boolean isChecked) { ShoppingCartBean shoppingCartBean = shoppingCartBeanList.get(position); int currentCount = shoppingCartBean.getCount(); currentCount++; shoppingCartBean.setCount(currentCount); ((TextView) showCountView).setText(currentCount + ""); shoppingCartAdapter.notifyDataSetChanged(); statistics(); } /** * 删减 * * @param position 组元素位置 * @param showCountView 用于展示变化后数量的View * @param isChecked 子元素选中与否 */ @Override public void doDecrease(int position, View showCountView, boolean isChecked) { ShoppingCartBean shoppingCartBean = shoppingCartBeanList.get(position); int currentCount = shoppingCartBean.getCount(); if (currentCount == 1) { return; } currentCount--; shoppingCartBean.setCount(currentCount); ((TextView) showCountView).setText(currentCount + ""); shoppingCartAdapter.notifyDataSetChanged(); statistics(); } /** * 删除 * * @param position */ @Override public void childDelete(int position) { shoppingCartBeanList.remove(position); shoppingCartAdapter.notifyDataSetChanged(); statistics(); }}
自此,购物车的功能基本已经实现了,剩下的是支付结算功能了。
Demo源码:
https://github.com/caichengan/ShoppingCartActivity
参考文章:http://blog.csdn.net/u011011744/article/details/53538972
为大家推荐一个网站,在这里可以找到你所需要的图标,颜色可以自己调色,本文中用到的图标也是在上面下载来的。
http://www.iconfont.cn/collections/index?spm=a313x.7781069.1998910419.2.I73Qfz
作者:破荒之恋
链接:http://www.jianshu.com/p/779447f33aaa
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
更多相关文章
- Android开发当中Parcelable,Serializable接口的使用
- Android解析中国天气接口JSon数据,应用于天气查询!
- Android 背景透明度设置和设置GridView元素间距
- android 语音识别接口开发。
- 【译】Android 23最新接口变化(Android API Differences Report)
- Cocos2d-x从C++端调用Android端的非静态函数接口