Android 购物车功能的实现首先,众所周知,ListView是Android最常用的控件,可以说是最简单的控件,也可以说是最复杂的控件。 作为一个Android初级开发者,可能会简单的ListView展示图文信息。 作为一个有一定项目开发经验的Android开发者来说,可能会遇到ListView的列表项中存在各种按钮的需求。 需求最多的就是购物车功能。想必大家都用过某宝某东客户端APP吧 ,就是那个购物车的功能。 ------------------------------------------------------------------------------------------------------------- 曾经做过购物车功能,今天项目需求也用到了差不多效果的购物车功能,刚好园友问了这个问题,便帮忙解答了。 之后,想了想还是写一下关于购物车效果的博客吧。 -------------------------------------------------------------------------------------------------------------- 那么现在就学习一下购物车功能的实现原理 首先让我们分析下实现购物车功能需要解决的问题: 1、在哪里处理按钮的点击响应事件,是适配器 还是 Activity或者Fragment 2、如何知道你点击的按钮是哪一个列表项中的 3、点击某个按钮的时候,如果列表项所需的数据改变了,如何更新UI 4、列表项中存在会获取焦点的各种按钮,会导致列表项无法点击,只能点击按钮,这种情况怎么解决
首先,我们必须要了解: 1、自定义适配器,不会的看下博客:安卓开发_浅谈ListView(自定义适配器) 2、接口回调,不会接口回调的可以看下博客:Android接口回调机制 一个ListView数据展示的实现,必须要有的 自定义适配器,数据源,ListView,列表项布局 做一个Demo,看下效果 (1)、效果一,点击商品添加删除数量,后面的商品总价随之变化 (2)、效果二,一个列表项发生变化,滑出界面,在滑回来,该列表项的数据依然存在,列表项的复用不存在问题 一、创建布局文件 1、主布局
main.xml
2、列表项布局
item_cart.xml
这里解决问题:列表项中存在会获取焦点的各种按钮,会导致列表项无法点击,只能点击按钮,这种情况怎么解决 解决方法,在item列表项布局的最外层父容器中 设置一个属性: android:descendantFocusability="blocksDescendants"
二、创建实体类 看上图,只需要三个属性,名称,总价格,数量
Product.java
三、创建适配器(关键!!) 1、创建适配器成员变量 //集合 ,存放ListView的商品实体类数据 private List<Product> products; //上下文 private Context context; //第一步,设置接口 private View.OnClickListener onAddNum; //加商品数量接口 private View.OnClickListener onSubNum; //减商品数量接口 接口看你具体需求,我这里是ImageButton ,所以是 View.OnClickListener 具体看情况,举三个列子,当然还有很多接口,比如单选按钮的 2、创建构造方法: public ShopAdapter(List<Product> products, Context context) { this.products = products; this.context = context; } 3、创建接口方法 public void setOnAddNum(View.OnClickListener onAddNum){ this.onAddNum = onAddNum; } public void setOnSubNum(View.OnClickListener onSubNum){ this.onSubNum = onSubNum; } 4、重写自定义适配器的除了getView()的三个方法 @Override public int getCount() { int ret = 0; if (products != null) { ret = products.size(); } return ret; } @Override public Object getItem(int i) { return products.get(i); } @Override public long getItemId(int i) { return i; } 5、接下来就是重点了 定义内部类 private static class ViewHolder{ //商品名称,数量,总价 private TextView item_product_name; private TextView item_product_num; private TextView item_product_price; //增减商品数量按钮 private ImageButton item_btn_add; private ImageButton item_btn_sub; } 重写最重要的getView()方法,主要看红色颜色部分 @Override public View getView(int i, View view, ViewGroup viewGroup) { View v = null; if (view != null) { v = view; }else{ v = LayoutInflater.from(context).inflate(R.layout.item_cart,viewGroup,false); } ViewHolder holder = (ViewHolder) v.getTag(); if (holder == null) { holder = new ViewHolder(); holder.item_product_name = (TextView) v.findViewById(R.id.item_product_name); holder.item_product_num = (TextView) v.findViewById(R.id.item_product_num); holder.item_product_price = (TextView) v.findViewById(R.id.item_product_price); //设置接口回调,注意参数不是上下文,它需要ListView所在的Activity或者Fragment处理接口回调方法 holder.item_btn_add = (ImageButton) v.findViewById(R.id.item_btn_add); holder.item_btn_add.setOnClickListener(onAddNum); holder.item_btn_sub = (ImageButton) v.findViewById(R.id.item_btn_sub); holder.item_btn_sub.setOnClickListener(onSubNum); } holder.item_product_name.setText(products.get(i).getName()); holder.item_product_num.setText(products.get(i).getNum()+""); holder.item_product_price.setText(products.get(i).getPrice() + ""); //设置Tag,用于判断用户当前点击的哪一个列表项的按钮,解决问题:如何知道你点击的按钮是哪一个列表项中的 holder.item_btn_add.setTag(i); holder.item_btn_sub.setTag(i); v.setTag(holder); return v; }
至此,自定义适配器部分完成了。 适配器完整代码:
适配器代码
四、主Activity public class MainActivity extends Activity implements View.OnClickListener, AdapterView.OnItemClickListener { private List<Product> datas; //数据源 private ShopAdapter adapter; //自定义适配器 private ListView listView; //ListView控件 @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); listView = (ListView) findViewById(R.id.listView); // 模拟数据 datas = new ArrayList<Product>(); Product product = null; for (int i = 0; i < 30; i++) { product = new Product(); product.setName("商品:"+i+":单价:"+i); product.setNum(1); product.setPrice(i); datas.add(product); } adapter = new ShopAdapter(datas,this); listView.setAdapter(adapter); //以上就是我们常用的自定义适配器ListView展示数据的方法了 3、点击某个按钮的时候,如果列表项所需的数据改变了,如何更新UI @Override public void onClick(View view) { Object tag = view.getTag(); switch (view.getId()){ case R.id.item_btn_add: //点击添加数量按钮,执行相应的处理 // 获取 Adapter 中设置的 Tag if (tag != null && tag instanceof Integer) { //解决问题:如何知道你点击的按钮是哪一个列表项中的,通过Tag的position int position = (Integer) tag; //更改集合的数据 int num = datas.get(position).getNum(); num++; datas.get(position).setNum(num); //修改集合中商品数量 datas.get(position).setPrice(position*num); //修改集合中该商品总价 数量*单价
---------------------------------------------------------------------------------------------------- 总结下: 1、有人说列表项中最好不要用ImageButton,而尽可能的用ImageView替代,目前没有发现使用ImageButton会发生什么错误 2、有人说列表项中 解决焦点问题需要两步: (1)、最外层父容器需要加属性: android:descendantFocusability="blocksDescendants" (2)、能获取焦点的控件,Button,ImageButton等等 需要 有属性:android:focusable="false" 但是我实际测试 发现子空间不需要设置focusable属性也不会产生问题,当然加上也没有问题 3、没有做过列表项中存在EditText控件的情况,可能会有焦点冲突。毕竟购物车中加一个编辑框也很少见
最后,一个实际的购物车,当然还需要显示当前的总金额,包含“去结算”按钮的功能的那一个框,这不属于ListView 如图: 那么怎么处理当你操作列表项中的按钮,不仅列表项中的数据发生变哈,而且不属于列表项的下面部分的“合计”数据也发生变化呢, 这就要学习Adapter中观察者模式的应用 了。 --------------------------------------------------------------------------------------------- 以上内容,如有错误,欢迎指出!
|
|