一个可以左滑删除的完整购物车DelSlideExpandableListView

我叫小马,我在坚持写一些东西,希望互相学习.我的博客是http://blog.csdn.net/maqianli23

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

介绍一下我在项目中写过的一个购物车。有以下功能:左滑删除商品;全选、多选、单选结算价钱,删除商品,增减商品数量

一般购物车运用到功能就这些了吧。接下来主要介绍一下他的左滑删除共呢个完整代码已经抽取成了一个demo.我会在最后把地址贴出来。其实原理很简单,就是ExpandableListView扩展成一个DelSlideExpandableListView,控件一共有两个,一个DelSlideExpandableListView,和一个包裹着子视图可滑动部分的ScrollLinerLayout.

接下来看代码吧。昨天晚上我 把所有的几乎都加上了注释 很容易理解了。

先放布局 cativity_main.xml:购物车的主体布局

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.mql.shoppingcardemo.MainActivity">
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_marginBottom="50dp"
            android:orientation="vertical">
            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="44dp"
                android:background="@color/colorPrimary"
                android:orientation="horizontal">
                <TextView
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:gravity="center"
                    android:text="购物车"
                    android:textColor="#ffffff"
                    android:textSize="17sp" />
            </LinearLayout>
            <View
                android:layout_width="match_parent"
                android:layout_height="1dp"
                android:background="#ff0000" />
            <com.example.mql.shoppingcardemo.DelSlideExpandableListView
                android:id="@+id/exListView"
                android:layout_width="match_parent"
                android:layout_height="0dp"
                android:layout_weight="8"
                android:childIndicator="@null"
                android:groupIndicator="@null"
                android:divider="@color/transparent"
                android:scrollbars="none">

            </com.example.mql.shoppingcardemo.DelSlideExpandableListView>
        </LinearLayout>
        <LinearLayout
            android:id="@+id/ll_shoppingCar_bottom"
            android:layout_width="match_parent"
            android:layout_height="50dp"
            android:background="#ffffff"
            android:layout_alignParentBottom="true"
            android:orientation="horizontal">
            <LinearLayout
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="3"
                android:background="#444444"
                android:gravity="center_vertical"
                android:orientation="horizontal">
                <CheckBox
                    android:id="@+id/all_chekbox"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center_vertical"
                    android:layout_marginLeft="10dp"
                    android:layout_marginRight="4dp"
                    android:checkMark="?android:attr/listChoiceIndicatorMultiple"
                    android:checked="false"
                    android:gravity="center"
                    android:minHeight="64dp"
                    android:paddingLeft="10dp"
                    android:textAppearance="?android:attr/textAppearanceLarge"
                    android:visibility="visible" />
                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginLeft="2dp"
                    android:paddingRight="10dp"
                    android:text="全选"
                    android:textColor="#ffffff"
                    android:textSize="16sp"
                    android:textStyle="bold" />
                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginLeft="5dp"
                    android:text="合计:"
                    android:textColor="#ffffff"
                    android:textSize="16sp"
                    android:textStyle="bold" />

                <TextView
                    android:id="@+id/tv_total_price"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="¥0.00"
                    android:textColor="#ffffff"
                    android:textSize="16sp"
                    android:textStyle="bold" />
            </LinearLayout>
            <TextView
                android:id="@+id/tv_delete"
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:background="#949494"
                android:clickable="true"
                android:gravity="center"
                android:text="删除"
                android:textColor="#FAFAFA" />

            <TextView
                android:id="@+id/tv_go_to_pay"
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:background="#d11e1a"
                android:clickable="true"
                android:gravity="center"
                android:text="结算(0)"
                android:textColor="#FAFAFA" />
        </LinearLayout>
</RelativeLayout>
接下来是 shopcar_group_item.xml: 这是商铺的布局

<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="44dp">
    <View
        android:layout_width="match_parent"
        android:layout_height="8dp"
        android:background="#f8f8f8"/>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="43dp"
        android:background="@color/transparent"
        android:orientation="horizontal">
        <CheckBox
            android:id="@+id/cb_checkStoreAll"
            android:layout_width="30dp"
            android:layout_height="20dp"
            android:layout_margin="12dp"
            android:layout_gravity="center"
            android:visibility="visible"
            />
        <ImageView
            android:id="@+id/riv_store"
            android:layout_width="20dp"
            android:layout_height="20dp"
            android:layout_marginLeft="10dp"
            android:layout_gravity="center"
            android:src="@mipmap/ic_launcher"
            android:layout_marginBottom="11dp"
            android:layout_marginTop="11dp"
            android:layout_marginRight="8dp"
            android:scaleType="fitXY"
            />
        <TextView
            android:id="@+id/tv_storeName"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:textColor="#333333"
            android:textSize="14sp"
            android:gravity="center|left"
            android:text="小马家的第一个马棚"/>
    </LinearLayout>
    <View
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:background="#e5e5e5"/>

</LinearLayout>
最后是shopcar_child_item.xml:这是商品的布局,里面包含了左划出现删除的布局

<com.example.mql.shoppingcardemo.ScrollLinerLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@color/transparent"
    android:orientation="horizontal">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="96dp"
        android:orientation="vertical">

        <LinearLayout
            android:id="@+id/forward_layout"
            android:layout_width="match_parent"
            android:layout_height="95dp"
            android:gravity="center_vertical"
            android:orientation="horizontal">

            <CheckBox
                android:id="@+id/cb_product"
                android:layout_width="0dp"
                android:layout_height="20dp"
                android:layout_gravity="center"
                android:layout_marginLeft="12dp"
                android:layout_marginRight="12dp"
                android:layout_weight="0.5"
                 />

            <ImageView
                android:id="@+id/iv_shopcar_product"
                android:layout_width="80dp"
                android:layout_height="80dp"
                android:layout_marginBottom="8dp"
                android:layout_marginTop="8dp"
                android:scaleType="fitXY"
                android:src="@mipmap/ic_launcher" />

            <LinearLayout
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_marginBottom="12dp"
                android:layout_marginLeft="8dp"
                android:layout_marginRight="8dp"
                android:layout_marginTop="12dp"
                android:layout_weight="4"
                android:orientation="vertical">

                <TextView
                    android:id="@+id/tv_product_name"
                    android:layout_width="match_parent"
                    android:layout_height="0dp"
                    android:layout_weight="1"
                    android:ellipsize="end"
                    android:lines="2"
                    android:text="hahahahahahhaahahahahahahahhahahahahaahahahahahahahhaahah"
                    android:textColor="#333333"
                    android:textSize="14sp"
                    android:textStyle="bold" />

                <LinearLayout
                    android:layout_width="match_parent"
                    android:layout_height="0dp"
                    android:layout_margin="5dp"
                    android:layout_marginBottom="16dp"
                    android:layout_weight="0.5"
                    android:orientation="horizontal">

                    <TextView
                        android:id="@+id/tv_product_price"
                        android:layout_width="0dp"
                        android:layout_height="match_parent"
                        android:layout_weight="1"
                        android:gravity="left|center|bottom"
                        android:text="1231"
                        android:textColor="#d11e1a"
                        android:textSize="17sp"
                        android:textStyle="bold" />

                    <Button
                        android:id="@+id/tv_reduce"
                        android:layout_width="24dp"
                        android:layout_height="24dp"
                        android:layout_gravity="center"
                        android:background="@drawable/btn_gray"
                        android:text="-"
                        android:textColor="#888888"
                        android:textStyle="bold"

                        />

                    <TextView
                        android:id="@+id/tv_product_number"
                        android:layout_width="25dp"
                        android:layout_height="25dp"
                        android:gravity="center"
                        android:singleLine="true"
                        android:text="1"

                        />

                    <Button
                        android:id="@+id/tv_add"
                        android:layout_width="24dp"
                        android:layout_height="24dp"
                        android:layout_gravity="center"
                        android:background="@drawable/btn_gray"
                        android:text="+"
                        android:textColor="#888888"
                        android:textStyle="bold" />
                </LinearLayout>
            </LinearLayout>
        </LinearLayout>

        <View
            android:layout_width="match_parent"
            android:layout_height="1dp"
            android:layout_marginLeft="8dp"
            android:layout_marginRight="8dp"
            android:background="@mipmap/view" />

    </LinearLayout>


    <TextView
        android:id="@+id/delete_action"
        android:layout_width="@dimen/delete_action_len"
        android:layout_height="match_parent"
        android:layout_gravity="center"
        android:background="#d11e1a"
        android:gravity="center"
        android:padding="7dp"
        android:text="delete"
        android:textColor="#FFF"
        android:textSize="18dp" />

</com.example.mql.shoppingcardemo.ScrollLinerLayout>


接下来贴出 DelSlideExpandableListView的代码:

public class DelSlideExpandableListView extends ExpandableListView implements GestureDetector.OnGestureListener, View.OnTouchListener {
    //手势监听
    private GestureDetector mDetector;
    private String TAG = "xiaoma";

    public DelSlideExpandableListView(Context context) {
        super(context);
        init(context);
    }

    public DelSlideExpandableListView(Context context, AttributeSet att) {
        super(context, att);
        init(context);
    }

    private int standard_touch_target_size = 0;
    private float mLastMotionX;
    // 有item被拉出
    public boolean deleteView = false;
    // 当前拉出的view
    private ScrollLinerLayout mScrollLinerLayout = null;
    // 滑动着
    private boolean scroll = false;
    // 禁止拖动
    private boolean forbidScroll = false;
    // 禁止拖动
    private boolean clicksameone = false;
    // 当前拉出的位置
    private int position;
    // 消息冻结
    private boolean freeze = false;

    private void init(Context mContext) {
        mDetector = new GestureDetector(mContext, this);//创建手势监听类
        // mDetector.setIsLongpressEnabled(false);
        //出现删除的最大距离
        standard_touch_target_size = (int) getResources().getDimension(R.dimen.delete_action_len);
        this.setOnTouchListener(this);//设置监听
    }

    public void reset() {
        reset(false);
    }

    //重置
    public void reset(boolean noaction) {
        position = -1;
        deleteView = false;
        if (mScrollLinerLayout != null) {
            if (!noaction) {
                //滑出
                mScrollLinerLayout.snapToScreen(0);
                Log.e("xiaoma",22+"");
            } else {
                //滑回去
                mScrollLinerLayout.scrollTo(0, 0);
                Log.e("xiaoma",11+"");
            }
            mScrollLinerLayout = null;
        }

        scroll = false;
    }

    public boolean onDown(MotionEvent e) {//如果手势向下滑,则禁止一切滑动动作,将其设置为不滑动状态
        // Log.i(TAG, "onDown");
        mLastMotionX = e.getX();
        int p = this.pointToPosition((int) e.getX(), (int) e.getY()) - this.getFirstVisiblePosition();
        if (deleteView) {
            if (p != position) {
                // 吃掉,不在有消息
                freeze = true;
                return true;
            } else {
                clicksameone = true;
            }
        }
        position = p;
        scroll = false;
        return false;
    }

    public void onLongPress(MotionEvent e) {
        // Log.i(TAG, "onLongPress");
    }

    public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
        // Log.i(TAG, "onScroll" + e1.getX() + ":" + distanceX);
        // 第二次
        if (scroll) {
            int deltaX = (int) (mLastMotionX - e2.getX());
            if (deleteView) {//如果被拉出,则拉出的距离为
                deltaX += standard_touch_target_size;//一直在变da
            }
            if (deltaX >= 0 && deltaX <= standard_touch_target_size) {//判断是否在拉出
                mScrollLinerLayout.scrollBy(deltaX - mScrollLinerLayout.getScrollX(), 0);//横向滑动
            }
            return true;
        }
        if (!forbidScroll) {//没有禁止滑动
            forbidScroll = true;
            // x方向滑动,才开始拉动
            if (Math.abs(distanceX) > Math.abs(distanceY)) {//判断横向滑动大于Y
                View v = this.getChildAt(position);
                boolean ischild = v instanceof ScrollLinerLayout;
                if (ischild) {
                    mScrollLinerLayout = (ScrollLinerLayout) v;
                    scroll = true;
                    int deltaX = (int) (mLastMotionX - e2.getX());
                    if (deleteView) {
                        // 再次点击的时候,要把deltax增加
                        deltaX += standard_touch_target_size;
                    }
                    if (deltaX >= 0 && deltaX <= standard_touch_target_size) {
                        mScrollLinerLayout.scrollBy((int) (e1.getX() - e2.getX()), 0);
                    }
                }
            }
        }
        return false;
    }

    public void onShowPress(MotionEvent e) {
        // Log.i(TAG, "onShowPress");
    }

    public boolean onSingleTapUp(MotionEvent e) {
        // Log.i(TAG, "onSingleTapUp");
        return false;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (scroll || deleteView) {
            return true;
        }
        return super.onTouchEvent(event);
    }

    @Override
    public boolean onTouch(View v, MotionEvent event) {

        if (event.getAction() == MotionEvent.ACTION_UP || event.getAction() == MotionEvent.ACTION_CANCEL) {
            boolean isfreeze = freeze;
            boolean isclicksameone = clicksameone;
            forbidScroll = false;
            clicksameone = false;
            freeze = false;
            if (isfreeze) {
                // 上一个跟当前点击不一致 还原
                reset();
                return true;
            }
            int deltaX2 = (int) (mLastMotionX - event.getX());
            // 不存在
            // Log.i(TAG, "scroll:" + scroll + "deltaX2:" + deltaX2);
            if (scroll && deltaX2 >= standard_touch_target_size / 2) {
                mScrollLinerLayout.snapToScreen(standard_touch_target_size);
                deleteView = true;
                scroll = false;
                return true;
            }
            if (deleteView && scroll && deltaX2 >= -standard_touch_target_size / 2) {
                mScrollLinerLayout.snapToScreen(standard_touch_target_size);
                deleteView = true;
                scroll = false;
                return true;
            }
            if(isclicksameone||scroll){
                reset();
                return true;
            }
            reset();
        }
        if (freeze) {
            return true;
        }
        // Log.i(TAG, "onTouchEvent");
        return mDetector.onTouchEvent(event);

    }

    public void deleteItem() {
        Log.i(TAG, "deleteItem");
        reset(true);

    }

    /*
     * (non-Javadoc)
     *
     * @see android.view.GestureDetector.OnGestureListener#onFling(android.view.
     * MotionEvent, android.view.MotionEvent, float, float)
     */
    @Override
    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
        return false;
    }
}

然后是ScrollLinerLayout

public class ScrollLinerLayout extends LinearLayout {

   public ScrollLinerLayout(Context context, AttributeSet attrs) {
      super(context, attrs);
      init(context);
   }

   private void init(Context context) {
      mScroller = new Scroller(context);
   }

   private Scroller mScroller;

   @Override
   public void computeScroll() {
//    Log.i("Scroller", "computeScroll");
      if (mScroller.computeScrollOffset()) {//判断滑动是否结束
         scrollTo(mScroller.getCurrX(), 0);//估算滑动位移,使其滑动到指定位置
         postInvalidate();//刷新屏幕 ,调用后它会用handler通知UI线程重绘屏幕,
      }
   }


   public void snapToScreen(int whichScreen) {
      int curscrollerx = getScrollX();//得到目前的X坐标
      mScroller.startScroll(curscrollerx, 0, whichScreen - curscrollerx, 0, 500);//开始滚动起点,滚动的距离距离,和滚动的持续时间
      invalidate();//刷新View,必须是在UI线程中进行工作,重回界面

   }

}

先上传一个百度云地址:

链接: https://pan.baidu.com/s/1kVNl7wj 密码: ccc9 

我的github已经弄好了。。。

传送门:https://github.com/yuyunhai/shoppingCar

评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值