Android實現電商購物車模組
前言:先上一張效果圖我們分析分析
由上圖可知,一個功能完備的購物車至少要包括:店鋪,店鋪滿減活動,店鋪滿減資訊,商品,滿多少免配送費,頁面商品全選,同一店鋪商品全選(包括反選),選中合計金額,總額,刪除購物車商品,結算調起支付頁面,實時修改商品數量
首先我們去實現介面,按照上圖所示,可以清晰的看到稍微繁瑣的就是商品列表,其他控制元件完全就是系統控制元件,這裡提一點複選框CheckBox,CheckBox有預設的外形,當然我們一般會去自定義樣式(UI美眉要與眾不同的,必須滿足),其實很簡單隻要我們在XML佈局中給CheckBox的button屬性配置一個狀態選擇器就好,選擇器裡設定state_checked= true時讓它展示一種圖片,為false的時候展示另一個圖片就好。
然後我們開始寫商品列表,可以看到購物車的商品列表是按照店鋪為第一層來分類的,商品是放在店鋪下邊的子類中,這種型別的資料只使用ListView(RecycleView也是一樣)是不好實現的,後來我找到一個繼承ListView的可擴充套件的控制元件ExpandableListView來實現,配合它使用的介面卡是BaseExpandableListAdapter。在做這一步的時候,產品小姐姐說我們來個側滑刪除吧,這樣使用者體驗好一點,那麼應該怎麼實現呢?
思路是這樣滴!側滑刪除肯定是刪除商品對不對,所以我們不能滑動店鋪的時候也整出來個側滑刪除,當然一個店鋪下將其所有商品都給刪完了,那這個店鋪絕對不會還杵在那,言歸正傳,我們可以做出來一個矩形裡邊寫個刪除,在使用者手指向右到左滑動的時候,將刪除這個滑塊展示出來,點選這個滑塊,跑刪除介面重新整理UI,
這樣就又引出來一個知識點---自定義View,先貼一段程式碼
package com.online_retailers.view.shoppingcart; import android.content.Context; import android.content.res.Resources; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.widget.LinearLayout; import android.widget.Scroller; import android.widget.TextView; import com.online_retailers.R; public class SlideView extends LinearLayout implements View.OnClickListener { public static final String TAG = "SlideView"; private static final int TAN = 2; private int mHolderWidth = 90; private float mLastX = 0; private float mLastY = 0; private LinearLayout mViewContent; private Scroller mScroller; private Context mContext; private Resources mResources; public TextView getBack() { return back; } private TextView back; public SlideView(Context context, Resources resources, View content) { super(context); initView(context, resources, content); } public SlideView(Context context, AttributeSet attrs) { super(context, attrs); // TODO Auto-generated constructor stub initView(context, context.getResources(), null); } public SlideView(Context context) { super(context); initView(context, context.getResources(), null); } private void initView(Context context, Resources resources, View content) { setOrientation(LinearLayout.HORIZONTAL); this.mContext = context; this.mResources = resources; mScroller = new Scroller(context); View view = LayoutInflater.from(context).inflate(resources.getLayout(R.layout.slide_view_merge), this); back = (TextView) view.findViewById(R.id.back); back.setOnClickListener(this); mViewContent = (LinearLayout) view.findViewById(R.id.view_content); mHolderWidth = getResources().getDimensionPixelSize(R.dimen.width_); if (content != null) { mViewContent.addView(content); } } @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_MOVE: float x = event.getX(); float y = event.getY(); float deltaX = x - mLastX; float deltaY = y - mLastY; mLastX = x; mLastY = y; if (Math.abs(deltaX) < Math.abs(deltaY) * TAN) { break; } if (deltaX != 0) { float newScrollX = getScrollX() - deltaX; if (newScrollX < 0) { newScrollX = 0; } else if (newScrollX > mHolderWidth) { newScrollX = mHolderWidth; } this.scrollTo((int) newScrollX, 0); } break; } return super.onTouchEvent(event); } private void smoothScrollTo(int destX, int destY) { int scrollX = getScrollX(); int delta = destX - scrollX; mScroller.startScroll(scrollX, 0, delta, 0, Math.abs(delta) * 3); invalidate(); } @Override public void computeScroll() { if (mScroller.computeScrollOffset()) { scrollTo(mScroller.getCurrX(), mScroller.getCurrY()); postInvalidate(); } } /** * 獲取view是需要重置快取狀態 */ public void shrink() { int offset = getScrollX(); if (offset == 0) { return; } scrollTo(0, 0); } public void setContentView(View view) { if (mViewContent != null) { mViewContent.addView(view); } } public void reset() { int offset = getScrollX(); if (offset == 0) { return; } smoothScrollTo(0, 0); } public void adjust(boolean left) { int offset = getScrollX(); if (offset == 0) { return; } if (offset < 20) { this.smoothScrollTo(0, 0); } else if (offset < mHolderWidth - 20) { if (left) { this.smoothScrollTo(mHolderWidth, 0); } else { this.smoothScrollTo(0, 0); } } else { this.smoothScrollTo(mHolderWidth, 0); } } @Override public void onClick(View v) { } }
我們來分析這個自定義的矩形,首先來回顧一下,我們這個自定義矩形是要接在ExpandedList列表中具體的每個item商品佈局上的,也就是說,這個自定義View是使用在adapter介面卡上,怎麼將自定義View放到adapter介面卡的getView中,設計思路是這樣的:
還記得怎麼給LinearLayout在程式碼中新增佈局嗎?new LinearLayout().addView(View view)
- 自定義View中,xml佈局檔案預留一個空白的LinearLayout
- 將adapter中getView方法裡item的佈局View傳給這個自定義View;
- findById到這個LinearLayout,addView這個adapter介面卡的佈局View,其實這就是上述程式碼中initView做的工作
這樣設定之後,自定義View和原本的adapter佈局就連線到一起了,這時的佈局在預設狀態是原來的adapter條目item,側滑刪除那個小滑塊是不展示的,至於說怎麼側滑才能將產品需要的側滑做出來,這就是Touch事件來控制的效果,繼續往下走:
Touch事件屬於Android事件分發範圍,如果有人不太熟悉可以看看這一篇:Android事件分發機制,