RecyclerView 侧滑删除,修改等,和 QQ 效果一致

先看效果:

可侧滑删除修改的的 SlideRecyclerView ,继承Recycler View,重写 onTouchEvent方法

public class SlideRecyclerView extends RecyclerView {
    private String TAG = "SlideRecyclerView";
    private int mMaxScrollWidth;
    private boolean isRlvScrolling;
    private int lastRlvScrollState;
    private boolean isItemStartScroll;
    private VelocityTracker mVelocityTracker;
    private Scroller mScroller;
    private int mItemState;//0:关闭,1:将要关闭,2:将要打开,3:打开
    private View mItemLayout;

    private int downX=0;
    private int downY=0;
    private boolean isItemEnterMoving;
    private int mPosition;
    private int lastX ;
    private int lastY ;
    private OnItemClickListener onItemClickListener;
    private int lastOperatePositon;
    private boolean isMoved;
    private int deleteWidth;
    private int updateWidth;



    public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
        this.onItemClickListener = onItemClickListener;
    }

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

    public SlideRecyclerView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public SlideRecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init();
    }

    private void init(){
        mVelocityTracker = VelocityTracker.obtain();
        mScroller  = new Scroller(getContext());
    }



    @Override
    public boolean onTouchEvent(MotionEvent e) {
        mVelocityTracker.addMovement(e);

        switch (e.getAction()) {
            case MotionEvent.ACTION_DOWN:
                isMoved = false;
                isItemEnterMoving = false;

                downX =  (int) (e.getX() + 0.5f);
                downY =  (int) (e.getY() + 0.5f);

                lastX = downX;
                lastY = downY;

                View view = findChildViewUnder(downX, downY);
                if (view == null) {
                    return false;
                }
                ViewHolder viewHolder =  getChildViewHolder(view);
                //首先获取位置
                mPosition = viewHolder.getAdapterPosition();

                //关闭状态
                if (mItemState == 0) {
                    mItemLayout = view;
                    updateWidth = mItemLayout.findViewById(R.id.view_item_update).getWidth();
                    deleteWidth = mItemLayout.findViewById(R.id.view_item_delete).getWidth();
                    mMaxScrollWidth = updateWidth + deleteWidth;
                    //在这里其他状态统统关闭,不然会导致还没关闭就出现点击事件(h)
                } else if (mItemState == 3 || mItemState == 2 || mItemState == 1) {
                    //如果点击的不是上一个,就关闭上一个
                    if (lastOperatePositon != mPosition){
                        mScroller.startScroll(mItemLayout.getScrollX(), 0, /*-mMaxScrollWidth*/ 0 -mItemLayout.getScrollX(), 0, 400);
                        invalidate();
                        mItemState = 0;
                        return false;//防止走UP 事件,防止响应点击事件
                    }else {
                        //return true 继续调用onTouchEvent
                        return true;
                    }
                }
                break;
            case MotionEvent.ACTION_MOVE:
                int currX = (int) (e.getX() + 0.5f);
                int currY = (int) (e.getY() + 0.5f);
                //移动距离
                int moveX = currX - downX;
                int moveY = currY - downY;

                int dx = currX - lastX;
                int dy = currY - lastY;
                //移动了就不响应点击事件
                if (Math.abs(moveX) >16 || Math.abs(moveY) > 16){
                    isMoved = true;
                }

                if (Math.abs(moveX) > Math.abs(moveY)) {
                    isItemEnterMoving = true;
                }

                int scrollX = mItemLayout.getScrollX();
                Log.d(TAG, "onTouchEvent: @@@@@@ ACTION_MOVE isRlvScrolling = " + isRlvScrolling);
                Log.d(TAG, "onTouchEvent: @@@@@@ ACTION_MOVE isItemEnterMoving= " + isItemEnterMoving  );
                if(isItemEnterMoving && !isRlvScrolling){
                    if (scrollX - dx >= mMaxScrollWidth) {//防止左滑过多
                        mItemLayout.scrollTo(mMaxScrollWidth, 0);
                        lastX = currX;
                        lastY = currY;
                        return true;
                    } else if (scrollX - dx <= 0) {//防止右滑过多
                        mItemLayout.scrollTo(0, 0);
                        lastX = currX;
                        lastY = currY;
                        return true;
                    }
                    Log.d(TAG, "onTouchEvent: scrollX = " + scrollX  );
                    Log.d(TAG, "onTouchEvent: -dx = " + (-dx ) );
                    mItemLayout.scrollBy(-dx, 0);//item跟随手指滑动
                    Log.d(TAG, "onTouchEvent: scrollX New = " + mItemLayout.getScrollX()  );
                    lastX = currX;
                    lastY = currY;
                    return true;
                }
                break;
            case MotionEvent.ACTION_UP:
                lastOperatePositon = mPosition;
                if (isRlvScrolling){
                    return super.onTouchEvent(e);
                }
                mVelocityTracker.computeCurrentVelocity(1000);//计算手指滑动的速度
                float xVelocity = mVelocityTracker.getXVelocity();//水平方向速度(向左为负)
//                float yVelocity = mVelocityTracker.getYVelocity();//垂直方向速度

                int deltaX = 0;
                int upScrollX = mItemLayout.getScrollX();

                if (Math.abs(xVelocity) > 100 /*&& Math.abs(xVelocity) > Math.abs(yVelocity)*/) {
                    if (xVelocity <= -100) {//左滑速度大于100,则打开item
                        deltaX = mMaxScrollWidth - upScrollX;
                        mItemState = 2;
                    } else if (xVelocity > 100) {//右滑速度大于100,则关闭item
                        deltaX = -upScrollX;
                        mItemState = 1;
                    }
                } else {
                    if (upScrollX >= mMaxScrollWidth / 2) {//item的左滑动距离大于侧滑View宽度的一半,则打开item
                        deltaX = mMaxScrollWidth - upScrollX;
                        mItemState = 2;
                    } else if (upScrollX < mMaxScrollWidth / 2) {//否则隐藏
                        deltaX = -upScrollX;
                        mItemState = 1;
                    }
                }

                //item自动滑动到指定位置
                mScroller.startScroll(upScrollX, 0, deltaX, 0, 400);
                isItemStartScroll = true;
                invalidate();
                mVelocityTracker.clear();

                //点击事件
                int x = (int) (e.getX()+0.5f);
                //&& isMoved   移动的情况下不响应点击事件
                if (null != onItemClickListener && !isMoved){
                    if (0 == mItemLayout.getScrollX()){
                        onItemClickListener.onItemClick(mItemLayout,mPosition);
                    }else if (mMaxScrollWidth == mItemLayout.getScrollX()){
                        if (x >=0 && x < getWidth() - mMaxScrollWidth){
                            onItemClickListener.onItemClick(mItemLayout,mPosition);
                        }else if (x>= getWidth() - mMaxScrollWidth && x < getWidth() - deleteWidth){
                            onItemClickListener.onUpdateClick(mItemLayout,mPosition);
                        }else if (x >= getWidth() - deleteWidth && x<=getWidth()){
                            onItemClickListener.onDeleteClick(mItemLayout,mPosition);
                        }
                    }
                }
                break;
        }
        return super.onTouchEvent(e);
    }

    public void computeScroll() {
        if (mScroller.computeScrollOffset()) {
            mItemLayout.scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
            invalidate();
        } else if (isItemStartScroll) {
            isItemStartScroll = false;
            if (mItemState == 1) {
                mItemState = 0;
            }
            if (mItemState == 2) {
                mItemState = 3;
            }
        }
    }

    public void onScrollStateChanged(int state) {
        super.onScrollStateChanged(state);
        isRlvScrolling = (state == SCROLL_STATE_DRAGGING  &&  lastRlvScrollState == SCROLL_STATE_IDLE);
        lastRlvScrollState= state;
    }
    public interface OnItemClickListener {
        void onDeleteClick(View itemView, int position);
        void onUpdateClick(View itemView, int position);
        void onItemClick(View itemView, int position);
    }
}

 

 

item 布局文件:




    

    

    




使用:

布局文件中使用

    

点击事件:
recyclerview.setOnItemClickListener(new SlideRecyclerView.OnItemClickListener() {
            @Override
            public void onDeleteClick(View itemView, int position) {
                Toast.makeText(CustomViewActivity.this,"删除",Toast.LENGTH_SHORT).show();
            }

            @Override
            public void onUpdateClick(View itemView, int position) {
                Toast.makeText(CustomViewActivity.this,"修改",Toast.LENGTH_SHORT).show();
            }

            @Override
            public void onItemClick(View itemView, int position) {
                Toast.makeText(CustomViewActivity.this,"内容",Toast.LENGTH_SHORT).show();
            }
        });

参考博客:https://www.jianshu.com/p/9bfed6e127cc

你可能感兴趣的:(Android,自定义View)