Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> Android開發 >> 關於android開發 >> Android 購物車功能的實現,android購物車實現

Android 購物車功能的實現,android購物車實現

編輯:關於android開發

Android 購物車功能的實現,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、主布局

1 <?xml version="1.0" encoding="utf-8"?> 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 android:orientation="vertical" 4 android:layout_width="fill_parent" 5 android:layout_height="fill_parent" 6 > 7 <ListView 8 android:layout_width="fill_parent" 9 android:layout_height="wrap_content" 10 android:id="@+id/listView" 11 /> 12 </LinearLayout> main.xml

2、列表項布局

1 <?xml version="1.0" encoding="utf-8"?> 2 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 android:layout_width="match_parent" 4 android:layout_height="match_parent" 5 android:background="#fff" 6 android:descendantFocusability="blocksDescendants" 7 > 8 <TextView 9 android:id="@+id/item_product_name" 10 android:layout_width="wrap_content" 11 android:layout_height="wrap_content" 12 android:textSize="20sp" 13 android:layout_margin="10dp" 14 android:text="商品名稱" 15 android:textColor="#000" 16 /> 17 <ImageButton 18 android:id="@+id/item_btn_add" 19 android:layout_width="wrap_content" 20 android:layout_height="wrap_content" 21 android:background="#0000" 22 android:src="@drawable/add" 23 android:layout_below="@+id/item_product_name" 24 android:layout_marginLeft="10dp" 25 /> 26 <TextView 27 android:id="@+id/item_product_num" 28 android:text="1" 29 android:layout_width="wrap_content" 30 android:layout_height="wrap_content" 31 android:textSize="25sp" 32 android:textColor="#000" 33 android:layout_margin="5dp" 34 android:layout_toRightOf="@id/item_btn_add" 35 android:layout_below="@id/item_product_name" 36 /> 37 <ImageButton 38 android:id="@+id/item_btn_sub" 39 android:layout_width="wrap_content" 40 android:layout_height="wrap_content" 41 android:background="#0000" 42 android:src="@drawable/sub" 43 android:layout_below="@id/item_product_name" 44 android:layout_toRightOf="@id/item_product_num" 45 /> 46 <TextView 47 android:id="@+id/item_product_price" 48 android:layout_width="wrap_content" 49 android:layout_height="wrap_content" 50 android:textSize="20sp" 51 android:layout_margin="10dp" 52 android:text="0" 53 android:textColor="#000" 54 android:layout_alignParentRight="true" 55 /> 56 57 </RelativeLayout> item_cart.xml

這裡解決問題:列表項中存在會獲取焦點的各種按鈕,會導致列表項無法點擊,只能點擊按鈕,這種情況怎麼解決

解決方法,在item列表項布局的最外層父容器中 設置一個屬性:

              android:descendantFocusability="blocksDescendants"

 

二、創建實體類

看上圖,只需要三個屬性,名稱,總價格,數量

1 package com.xqx.ShopDemo; 2 3 /** 4 * 購物車實體類 5 * 測試 6 */ 7 public class Product { 8 //商品名稱 9 private String name; 10 // 商品數量 11 private int num; 12 // 該商品總價 13 private int price; 14 15 @Override 16 public String toString() { 17 return "Product{" + 18 "name='" + name + '\'' + 19 ", num=" + num + 20 ", price=" + price + 21 '}'; 22 } 23 24 public void setName(String name) { 25 this.name = name; 26 } 27 28 public void setNum(int num) { 29 this.num = num; 30 } 31 32 public void setPrice(int price) { 33 this.price = price; 34 } 35 36 public String getName() { 37 return name; 38 } 39 40 public int getNum() { 41 return num; 42 } 43 44 public int getPrice() { 45 return price; 46 } 47 } 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;
    }

 

至此,自定義適配器部分完成了。

適配器完整代碼:

1 import android.content.Context; 2 import android.view.LayoutInflater; 3 import android.view.View; 4 import android.view.ViewGroup; 5 import android.widget.BaseAdapter; 6 import android.widget.ImageButton; 7 import android.widget.ImageView; 8 import android.widget.TextView; 9 10 import java.util.List; 11 12 /** 13 * 購物車功能 14 * 適配器 15 */ 16 public class ShopAdapter extends BaseAdapter{ 17 18 //集合 ,存放ListView的商品實體類數據 19 private List<Product> products; 20 //上下文 21 private Context context; 22 23 //第一步,設置接口 24 private View.OnClickListener onAddNum; 25 private View.OnClickListener onSubNum; 26 27 //第二步,設置接口方法 28 public void setOnAddNum(View.OnClickListener onAddNum){ 29 this.onAddNum = onAddNum; 30 } 31 32 public void setOnSubNum(View.OnClickListener onSubNum){ 33 this.onSubNum = onSubNum; 34 } 35 public ShopAdapter(List<Product> products, Context context) { 36 this.products = products; 37 this.context = context; 38 } 39 40 @Override 41 public int getCount() { 42 int ret = 0; 43 if (products != null) { 44 ret = products.size(); 45 } 46 return ret; 47 } 48 49 @Override 50 public Object getItem(int i) { 51 return products.get(i); 52 } 53 54 @Override 55 public long getItemId(int i) { 56 return i; 57 } 58 59 @Override 60 public View getView(int i, View view, ViewGroup viewGroup) { 61 View v = null; 62 if (view != null) { 63 v = view; 64 }else{ 65 v = LayoutInflater.from(context).inflate(R.layout.item_cart,viewGroup,false); 66 } 67 68 ViewHolder holder = (ViewHolder) v.getTag(); 69 if (holder == null) { 70 holder = new ViewHolder(); 71 holder.item_product_name = (TextView) v.findViewById(R.id.item_product_name); 72 holder.item_product_num = (TextView) v.findViewById(R.id.item_product_num); 73 holder.item_product_price = (TextView) v.findViewById(R.id.item_product_price); 74 75 //第三步,設置接口回調,注意參數不是上下文,它需要ListView所在的Activity或者Fragment處理接口回調方法 76 holder.item_btn_add = (ImageButton) v.findViewById(R.id.item_btn_add); 77 holder.item_btn_add.setOnClickListener(onAddNum); 78 79 holder.item_btn_sub = (ImageButton) v.findViewById(R.id.item_btn_sub); 80 holder.item_btn_sub.setOnClickListener(onSubNum); 81 82 } 83 84 holder.item_product_name.setText(products.get(i).getName()); 85 holder.item_product_num.setText(products.get(i).getNum()+""); 86 holder.item_product_price.setText(products.get(i).getPrice() + ""); 87 88 //第四步,設置Tag,用於判斷用戶當前點擊的哪一個列表項的按鈕 89 holder.item_btn_add.setTag(i); 90 holder.item_btn_sub.setTag(i); 91 92 v.setTag(holder); 93 return v; 94 } 95 private static class ViewHolder{ 96 //商品名稱,數量,總價 97 private TextView item_product_name; 98 private TextView item_product_num; 99 private TextView item_product_price; 100 //增減商品數量按鈕 101 private ImageButton item_btn_add; 102 private ImageButton item_btn_sub; 103 104 } 105 } 適配器代碼

四、主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展示數據的方法了

//解決問題:在哪裡處理按鈕的點擊響應事件,是適配器 還是 Activity或者Fragment,這裡是在Activity本身處理接口 //執行添加商品數量,減少商品數量的按鈕點擊事件接口回調 adapter.setOnAddNum(this); adapter.setOnSubNum(this); listView.setOnItemClickListener(this);
}
//


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); //修改集合中該商品總價 數量*單價
            //解決問題:點擊某個按鈕的時候,如果列表項所需的數據改變了,如何更新UI adapter.notifyDataSetChanged(); } break; case R.id.item_btn_sub: //點擊減少數量按鈕 ,執行相應的處理 // 獲取 Adapter 中設置的 Tag if (tag != null && tag instanceof Integer) { int position = (Integer) tag; //更改集合的數據 int num = datas.get(position).getNum(); if (num>0) { num--; datas.get(position).setNum(num); //修改集合中商品數量 datas.get(position).setPrice(position * num); //修改集合中該商品總價 數量*單價 adapter.notifyDataSetChanged(); } } break; } } @Override public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) { Toast.makeText(MainActivity.this,"點擊了第"+i+"個列表項",Toast.LENGTH_SHORT).show(); } }

 

----------------------------------------------------------------------------------------------------

總結下:

1、有人說列表項中最好不要用ImageButton,而盡可能的用ImageView替代,目前沒有發現使用ImageButton會發生什麼錯誤

2、有人說列表項中 解決焦點問題需要兩步:

(1)、最外層父容器需要加屬性:

android:descendantFocusability="blocksDescendants"

(2)、能獲取焦點的控件,Button,ImageButton等等  需要 有屬性:android:focusable="false"

但是我實際測試 發現子空間不需要設置focusable屬性也不會產生問題,當然加上也沒有問題

3、沒有做過列表項中存在EditText控件的情況,可能會有焦點沖突。畢竟購物車中加一個編輯框也很少見

 

最後,一個實際的購物車,當然還需要顯示當前的總金額,包含“去結算”按鈕的功能的那一個框,這不屬於ListView

如圖:

那麼怎麼處理當你操作列表項中的按鈕,不僅列表項中的數據發生變哈,而且不屬於列表項的下面部分的“合計”數據也發生變化呢,

這就要學習Adapter中觀察者模式的應用 了。

---------------------------------------------------------------------------------------------

以上內容,如有錯誤,歡迎指出!

 

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved