侧滑删除自定义view


public class DeleteView
        extends FrameLayout {

    private View           contentView;
    private View           deleteView;
    private int            contentWidth;
    private int            deleteWidth;
    private ViewDragHelper dragHelper;
    private int            dragWidth;

    private int STATE_OPEN = 0;
    private int STATE_CLOSE = 1;
    private int mState = STATE_CLOSE;
    float touchSlop;

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


    private void init() {

        dragHelper = ViewDragHelper.create(this,callback);
        // 获取系统认为的滑动的临界值
        touchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
    }

    /** 将拦截事件交给ViewDragHelper处理 */
    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        // 这里只是为了保证onTouchEvent可以执行
        if(!SwipeLayoutManager.getInstance().isCouldSwipe(DeleteView.this)) {
            return true;
        }
        return dragHelper.shouldInterceptTouchEvent(ev);
    }


    float downX, downY;
    long downTime;
    /** 将触摸事件交给ViewDragHelper处理 */
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        // SwipeLayout不可以侧滑时,关闭已经打开的SwipeLayout
        if(!SwipeLayoutManager.getInstance().isCouldSwipe(DeleteView.this)) {
            SwipeLayoutManager.getInstance().closeOpenInstance();
            return false;  // 这里返回true崩溃什么鬼 。
        }

        switch (event.getAction()) {

            case MotionEvent.ACTION_DOWN:
                downX = event.getX();
                downY = event.getY();
                // 记录按下的时间
                downTime = System.currentTimeMillis();
                break;
            case MotionEvent.ACTION_MOVE:

                float moveX = event.getX();
                float moveY = event.getY();

                // 水平滑动,不让listView拦截事件
                if(Math.abs(moveY-downY) < Math.abs(moveX-downX)) {
                    // 请求父View不拦截事件
                    requestDisallowInterceptTouchEvent(true);
                }

                break;
            case MotionEvent.ACTION_UP:
                // 记录擡起的时间点
                long upTime = System.currentTimeMillis();
                // 计算擡起的座标
                float upX = event.getX();
                float upY = event.getY();
                // 计算按下和擡起的时间差
                long touchDuration = upTime-downTime;
                // 计算按下点和擡起点的距离
                float touchD = getDistanceBetween2Points(new PointF(downX, downY), new PointF(upX, upY));

                // 模拟点击事件
                if(touchDuration < 400 && touchD < touchSlop){
                    // 打开状态则关闭,否则执行点击事件
                    if(SwipeLayoutManager.getInstance().isOpenInstance(DeleteView.this)) {
                        SwipeLayoutManager.getInstance().closeOpenInstance();
                    } else {
                        if(listener!=null){
                            listener.onClick();
                        }
                    }

                }
                break;
        }

        dragHelper.processTouchEvent(event);
        return true;
    }

    ViewDragHelper.Callback callback = new ViewDragHelper.Callback() {

        /** 确定需要触摸的View */
        @Override
        public boolean tryCaptureView(View child, int pointerId) {
            //Toast.makeText(getContext(), "事件捕获", Toast.LENGTH_SHORT).show();
            return child == contentView || child == deleteView;
        }

        /** View在水平方向的拖拽范围,不要返回0 */
        @Override
        public int getViewHorizontalDragRange(View child) {
            return dragWidth;
        }

        /**
         * 控制子View在水平方向移动
         * @param child 拖拽的View
         * @param left  手指滑动之后子ViewDragHelper认为的View的left
         * @param dx    手指在水平方向移动的距离
         * @return      子View最终的left
         */
        @Override
        public int clampViewPositionHorizontal(View child, int left, int dx) {
            if(child == contentView) {
                left = left > 0 ? 0 : left;
                left = left < -dragWidth ? -dragWidth : left;
            } else if(child == deleteView) {
                left = left > contentWidth ? contentWidth : left;
                left = left < contentWidth - deleteWidth ? contentWidth - deleteWidth
                                                         : left;
            }
            return left;
        }

        /**
         * View位置改变时调用,一般用来做伴随移动和判断状态执行相应的操作
         * @param changedView
         * @param left View当前的left
         * @param top  View当前的top
         * @param dx   View的水平移动距离
         * @param dy   View的竖直移动距离
         */
        @Override
        public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {
            if(changedView == contentView) {

                int newLeft = deleteView.getLeft() + dx;
                deleteView.layout(newLeft,getTop(), newLeft+deleteWidth,getBottom());

            } else if(changedView == deleteView) {
                contentView.layout(left - contentWidth,contentView.getTop(),
                                   left, contentView.getBottom());
            }

            // 处理打开与关闭的逻辑
            if(contentView.getLeft() == -deleteWidth && mState == STATE_CLOSE) {
                mState = STATE_OPEN;

                // 记录打开的SwipeLayout
                SwipeLayoutManager.getInstance().setOpenInstance(DeleteView.this);

            } else if(contentView.getLeft() == 0 && mState == STATE_OPEN) {
                mState = STATE_CLOSE;
                SwipeLayoutManager.getInstance().closeOpenInstance();
            }
        }

        /** 手指擡起的时候执行 */
        @Override
        public void onViewReleased(View releasedChild, float xvel, float yvel) {

            int width = contentWidth - dragWidth/2;
            if(contentView.getRight() < width) {
                openDeleteMenu();
            } else {
                closeDeleteMenu();
            }
        }
    };

    public void closeDeleteMenu() {
        dragHelper.smoothSlideViewTo(contentView,0,contentView.getTop());
        ViewCompat.postInvalidateOnAnimation(DeleteView.this);
    }

    public void openDeleteMenu() {
        dragHelper.smoothSlideViewTo(contentView,-dragWidth,contentView.getTop());
        ViewCompat.postInvalidateOnAnimation(DeleteView.this);
    }

    @Override
    public void computeScroll() {
        if(dragHelper.continueSettling(true)) {
            ViewCompat.postInvalidateOnAnimation(DeleteView.this);
        }
    }

    /** 对contentView和deleteView重新排版 */
    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        contentView.layout(left, top, right, bottom);
        deleteView.layout(right, top, right + deleteWidth, bottom);
    }

    /** 获取contentView和deleteView */
    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();
        // 做简单的异常处理
        if(getChildCount() != 2) {
            throw new IllegalArgumentException("the swipelayout only have 2 children!");
        }
        contentView = getChildAt(0);
        deleteView = getChildAt(1);
    }

    /** 获取contentView和deleteView的测量大小 */
    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        contentWidth = contentView.getMeasuredWidth();
        deleteWidth = deleteView.getMeasuredWidth();

        dragWidth = deleteWidth;
    }

    /** 获取删除区域 */
    public View getDeleteView() {
        return deleteView;
    }

    /** 获取内容区域 */
    public View getContentView() {
        return contentView;
    }


    private OnSwipeLayoutClickListener listener;
    public void setOnSwipeLayoutClickListener(OnSwipeLayoutClickListener listener){
        this.listener = listener;
    }

    /** 点击事件回调接口 */
    public interface OnSwipeLayoutClickListener{
        void onClick();
    }

    /**
     * 获得两点之间的距离
     * @param p0
     * @param p1
     * @return
     */
    public static float getDistanceBetween2Points(PointF p0, PointF p1) {
        return (float) Math.sqrt(Math.pow(p0.y - p1.y, 2) + Math.pow(p0.x - p1.x, 2));
    }
}

使用方法

<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="56dp"
  android:layout_marginLeft="30dp"
    android:layout_marginRight="30dp"
    >
    <view.DeleteView
        android:id="@+id/delete_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

//显示区域
    <RelativeLayout
        android:id="@+id/rl_item"
                    android:layout_marginTop="5dp"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:background="@color/white">

</RelativeLayout>

//删除区域
    <LinearLayout
        android:gravity="center_vertical"
        android:layout_gravity="center_vertical"
                  android:layout_width="wrap_content"
                  android:layout_height="35dp"
                  android:orientation="horizontal" >

        <TextView
            android:id="@+id/swipe_call"
            android:layout_width="10dp"
            android:layout_height="match_parent"
            android:textSize="18sp"
            android:textColor="#ffffff"
            android:gravity="center"
            android:background="#00000000"
            android:text=""/>

        <TextView
            android:layout_gravity="center_vertical"
            android:id="@+id/tv_delete"
            android:layout_width="80dp"
            android:layout_height="35dp"
            android:textSize="18sp"
            android:textColor="#ffffff"
            android:gravity="center"
            android:background="@drawable/delete_bg"
            android:text="删除"/>

    </LinearLayout>

</view.DeleteView>


</RelativeLayout>

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章