側滑刪除自定義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>

 

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