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)

  1. 自定义View中,xml布局文件预留一个空白的LinearLayout
  2. 将adapter中getView方法里item的布局View传给这个自定义View;
  3. findById到这个LinearLayout,addView这个adapter适配器的布局View,其实这就是上述代码中initView做的工作

  这样设置之后,自定义View和原本的adapter布局就连接到一起了,这时的布局在默认状态是原来的adapter条目item,侧滑删除那个小滑块是不展示的,至于说怎么侧滑才能将产品需要的侧滑做出来,这就是Touch事件来控制的效果,继续往下走:

  Touch事件属于Android事件分发范围,如果有人不太熟悉可以看看这一篇:Android事件分发机制

  • 2
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值