商城項目實戰 | 14.1 仿京東購物車的實現(一)

本文為菜鳥窩作者劉婷的連載。”商城項目實戰”系列來聊聊仿”京東淘寶的購物商城”如何實現。

商城項目之前已經完成了主頁、分類以及熱門三大模塊了,下面就是購物車了,商城項目中的購物車模塊是仿照京東商城而來的,在實現之前都要來看看效果圖。

效果圖
效果圖

在上一篇文章《商城項目實戰 | 13.1 Android 數據存儲之 SharedPreferences 的存儲方式和安全性》最后的結束語中也說過了,購物車模塊中的商品數據因為是用戶暫時存儲的商品、加上一般購物車中的商品不會太多,也沒必要上傳到網絡服務器中去,所以在后面的購物車的商品數據存儲我們也將使用 SharedPreferences 的存儲方式。那么我們先來實現購物車中的商品數據存儲。

實現購物車商品數據存儲

購物車的商品數據既然要使用 SharedPreferences 來存儲,那么我們首先就要寫一個專門存放 SharedPreferences 相關操作的工具類,用來對數據的讀寫處理。

1. 實現 SharedPreferences 工具類

新建文件 SharedPreferencesUtils,用于數據的讀寫操作,后期對于商品數據的操作可以直接調用該 class 中的方法,SharedPreferences 對于數據的操作非常簡單,我這里就展示下 int 類型數據的讀寫。

public static boolean putInt(Context context, String key, int value) {
        SharedPreferences settings = context.getSharedPreferences(PREFERENCE_NAME, Context.MODE_PRIVATE);
        SharedPreferences.Editor editor = settings.edit();
        editor.putInt(key, value);
        return editor.commit();
    }

    public static int getInt(Context context, String key) {
        return getInt(context, key, -1);
    }

    public static int getInt(Context context, String key, int defaultValue) {
        SharedPreferences settings = context.getSharedPreferences(PREFERENCE_NAME, Context.MODE_PRIVATE);
        return settings.getInt(key, defaultValue);
    }

SharedPreferences 的具體使用也可以參考文章《商城項目實戰 | 13.1 Android 數據存儲之 SharedPreferences 的存儲方式和安全性》。

2. 實現購物車數據存儲工具類

實現購物車數據存儲工具類主要是要實現對于 json 格式數據的轉化處理以及對數據的增刪改查操作。

2.1 轉化數據類型

新建 CartProvider class 文件,用于專門針對購物車中數據的操作,因為使用的數據都是 json 格式的數據,所以在存儲的過程中需要一定的轉化,例如將 ShoppingCartInfo 對象的 list 列表轉化為 SparseArray 類型的 datas,其中 ShoppingCartInfo 實體類就是購物車信息類,包括 count 數量和 isChecked 是否被選中兩個屬性。

private void listToSparse(){

        List<ShoppingCartInfo> carts =  getDataFromLocal();

        if(carts!=null && carts.size()>0){

            for (ShoppingCartInfo cart:
                    carts) {

                datas.put(cart.getId().intValue(),cart);
            }
        }

    }

    public  List<ShoppingCartInfo> getDataFromLocal(){

        String json = SharedPreferencesUtils.getString(mContext,CART_JSON);
        List<ShoppingCartInfo> carts =null;
        if(json !=null ){

            carts = JsonUtils.fromJson(json,new TypeToken<List<ShoppingCartInfo>>(){}.getType());

        }

        return  carts;

    }

其中的 getDataFromLocal() 方法是用于獲取本地數據,也將 json 格式的數據轉化為了 List 列表,這里需要第三方 json 數據處理的開源框架 Gson ,因此在 build.gradle 中不要忘記了添加 Gson 的依賴。

2.2 實現對數據的增刪改查

之前已經寫好了 SharedPreferencesUtils 文件的話,那么對于購物車中商品數據的增刪改查就很簡單了,直接調用里面的方法就好了。比如需要增加數據的時候。

public void put(ShoppingCartInfo cart){

        ShoppingCartInfo temp =  datas.get(cart.getId().intValue());

        if(temp !=null){
            temp.setCount(temp.getCount()+1);
        }
        else{
            temp = cart;
            temp.setCount(1);
        }

        datas.put(cart.getId().intValue(),temp);

        commit();

    }

    public void commit(){

        List<ShoppingCartInfo> carts = sparseToList();

        SharedPreferencesUtils.putString(mContext,CART_JSON,JsonUtils.toJSON(carts));

    }

增加數據的時候,就是要將 datas 中的數據都讀取出來,然后進行數據類型轉化,最后在 commit() 方法中直接調用了 SharedPreferencesUtils 中的 putString() 方法,本地存儲數據。

而刪除數據的處理也很類似,只要 調用 SparseArray.delete() 方法,修改數據則是直接調用 SparseArray.put() 方法,當然無論是增刪改中的哪種,最后都要調用 commit() 方法,對內存中的數據進行操作。

至于數據的查詢,之前就已經寫好了,直接調用 getDataFromLocal() 方法。

public List<ShoppingCartInfo> getAll(){
        return  getDataFromLocal();
    }

這就獲取到了本地存儲的所有數據了,也就是查詢數據的操作。

實現在熱門中添加商品到購物車

先看下熱門模塊的界面。

效果圖
效果圖

熱門商品列表模塊的實現請參考文章《商城項目實戰 | 8.2 SwipeRefreshLayout 實現可以下拉刷新和加載更多的熱門商品列表》,這里的商品列表的每一項中都有一個立即購買的按鈕,我們就實現點擊立即購買按鈕,將商品添加到購物車商品列表中。

要將商品添加到購物車商品列表中就是要為購物車商品列表添加數據,那么就要使用之前寫好的 CartProvider 中的 put(ShoppingCartInfo cart) 方法,因為是對列表 item 項中按鈕的操作,所以就要修改下熱門商品的 Adapter ,也就是 HWAdapter。修改如下,先聲明 CartProvider 。

private CartProvider provider ;

之后在 Adapter 的構造方法中創建好 CartProvider。

provider = new CartProvider(context);

為立即購買按鈕添加點擊事件監聽。

Button button =viewHolder.getButton(R.id.btn_add);

        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                provider.put(convertData(wares));
                ToastUtils.show(context,context.getString(R.string.added_to_cart));
            }
        });

convertData(WaresInfo item) 方法就是 new 一個 ShoppingCartInfo 對象,上面的代碼就是點擊立即購買后,將該 item 項目中的商品數據添加到本地存儲中,同時提示加入購物車成功。

顯示購物車商品

已經添加商品到購物車中,那么在購物車中也要將商品顯示出來。

1. 定義商品列表 item 布局

對于列表的實現,首先就是要寫好列表 item 項的布局。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@drawable/selector_list_item"
    android:padding="5dp"
    android:gravity="center_vertical"
    >

    <CheckBox
        android:id="@+id/cart_checkbox_item"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:focusable="false"
        android:clickable="false"
        style="@style/cart_check_box_style"
        android:layout_gravity="center"/>


    <LinearLayout
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="20dp"
        >

        <com.facebook.drawee.view.SimpleDraweeView
            android:id="@+id/cart_drawee_view"
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:layout_gravity="center"
            />


        <LinearLayout
            android:orientation="vertical"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginLeft="5dp"
            >


            <TextView
                android:id="@+id/cart_tv_title"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="20dp"
                android:textColor="@color/gray"
                android:textSize="14sp"
                android:maxLines="2"
                />

            <TextView
                android:id="@+id/cart_tv_price"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textSize="16sp"
                android:textColor="@color/crimson"
                android:layout_gravity="right"
                />

            <com.liuting.cniao_shop.widget.AddSubNumberLayout
                android:id="@+id/cart_layout_number"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginTop="10dp"
                app:value="1"
                app:minValue="1"
                app:variation="1"
                app:maxValue="10"
                app:btnAddBackground="@android:color/white"
                app:btnSubBackground="@android:color/white"
                app:textViewBackground="@android:color/white"
                app:textViewTextSize="16sp"
                app:btnSubTextSize="22sp"
                app:btnAddTextSize="22sp"
                />

        </LinearLayout>
    </LinearLayout>
</LinearLayout>

布局中有 checkbox 選擇按鈕、商品圖片、商品名稱、價格以及數字加減控件。

2. 定義商品列表 Adapter

Adapter 的實現很簡單了,新建 CartAdapter,代碼如下。

public class CartAdapter extends SimpleAdapter<ShoppingCartInfo> {

    public CartAdapter(Context context, List<ShoppingCartInfo> datas, final CheckBox checkBox, TextView tv) {
        super(context, R.layout.recycler_item_cart_layout, datas);
    }


    @Override
    protected void convert(BaseViewHolder viewHoder, final ShoppingCartInfo item) {

        viewHoder.getTextView(R.id.cart_tv_title).setText(item.getName());
        viewHoder.getTextView(R.id.cart_tv_price).setText("¥"+item.getPrice());
        SimpleDraweeView draweeView = (SimpleDraweeView) viewHoder.getView(R.id.cart_drawee_view);
        draweeView.setImageURI(Uri.parse(item.getImgUrl()));

        CheckBox checkBox = (CheckBox) viewHoder.getView(R.id.cart_checkbox_item);
        checkBox.setChecked(item.isChecked());


        AddSubNumberLayout numberAddSubView = (AddSubNumberLayout) viewHoder.getView(R.id.cart_layout_number);

        numberAddSubView.setValue(item.getCount());
    }

}

在 Adapter 中添加布局文件,然后聲明初始化好控件。

3. 實現購物車布局

購物車界面的布局根據上文中的效果圖,需要一個商品列表、全選按鈕、合計價格以及結算按鈕。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/cart_recycler_view"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        >

    </android.support.v7.widget.RecyclerView>

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:paddingTop="10dp"
        android:paddingBottom="10dp"
        android:paddingLeft="5dp"
        android:paddingRight="5dp"
        android:background="#802f4f4f"
        android:gravity="center_vertical"
        >

        <CheckBox
            android:id="@+id/cart_checkbox_all"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentLeft="true"
            android:layout_centerVertical="true"
            android:checked="true"
            android:text="@string/check_all"
            style="@style/cart_check_box_style"/>


        <TextView
            android:id="@+id/cart_tv_total"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_toRightOf="@+id/cart_checkbox_all"
            android:layout_marginLeft="@dimen/large_margin"
            android:layout_centerVertical="true"
            android:textSize="16sp"
            android:text="@string/sum"/>

        <Button
            android:id="@+id/cart_btn_order"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:layout_centerVertical="true"
            android:minHeight="40dp"
            android:minWidth="80dp"
            android:text="@string/go_to_buy"
            style="@style/bigRedButton"/>

    </RelativeLayout>
</LinearLayout>

布局文件的實現基本上都很簡單,沒有什么復雜的控件。

4. 實現商品列表顯示

布局都畫好了,下面就是為 RecyclerView 添加 Adapter,設置相關屬性就好了。

private void showData(){
        List<ShoppingCartInfo> carts = cartProvider.getAll();

        mAdapter = new CartAdapter(getContext(),carts,mCheckBox,mTextTotal);

        mRecyclerView.setAdapter(mAdapter);
        mRecyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
        mRecyclerView.addItemDecoration(new WareItemDecoration(getContext(),WareItemDecoration.VERTICAL_LIST));

    }

RecyclerView 的相關屬性配置好了,就算完成了商品列表的顯示,下面看效果。

效果圖

運行代碼獲取效果圖。

效果圖
效果圖

這是目前實現的效果,已經基本實現了購物車模塊的商品顯示了,但是商品的選擇、合計的計算以及編輯狀態的實現等都還沒有寫好,在下篇文章中會繼續詳細說明實現的方法和過程。

《Android群英傳》作者帶你解鎖設計布局的新姿勢 http://mp.weixin.qq.com/s/k7gCBJpiXK0g8Ed2FVHQ3A

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容