recyclerview仿qq滑动删除

滑动删除需要两个辅助类,三步即可完成。

第一个:这个类无需改动

public class LinearItemDecoration extends RecyclerView.ItemDecoration{

    private Paint   mPaint;
    private int     mColor;

    public LinearItemDecoration(@ColorInt int color) {
        mPaint = new Paint();
        mPaint.setColor(color);
        mPaint.setAntiAlias(true);
        mPaint.setDither(true);

    }

    public LinearItemDecoration() {
        this(0);
    }

    @Override
    public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
        int height = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 1, parent.getResources().getDisplayMetrics());
        RecyclerView.LayoutManager  layoutManager = parent.getLayoutManager();
        View childView ;
        RecyclerView.LayoutParams   layoutParams;
        int childCount = layoutManager.getChildCount();
        Rect  drawRect = new Rect();
        int top,left,right,bottom;

        for(int childIndex = 0 ; childIndex < childCount - 1; childIndex++){
            childView = layoutManager.getChildAt(childIndex);
            layoutParams = (RecyclerView.LayoutParams) childView.getLayoutParams();
            top = childView.getBottom() + layoutParams.bottomMargin;
            left = childView.getLeft() + layoutParams.leftMargin + childView.getPaddingLeft();
            right = childView.getRight() - childView.getPaddingRight() - layoutParams.rightMargin;
            bottom = top + height;
            drawRect.set(left,top,  right, bottom);
            c.drawRect(drawRect, mPaint);
        }
    }

    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
        int height = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 1, parent.getResources().getDisplayMetrics());
        outRect.set(0, 0, 0,  height);
    }
}

第二个:这个同样不需要改动,主要封了一个回掉的接口(见代码尾部)。

public class ItemSlideHelper implements RecyclerView.OnItemTouchListener, GestureDetector.OnGestureListener {


    private static final String TAG = "ItemSwipeHelper";


    private final int DEFAULT_DURATION = 200;

    private View mTargetView;

    private int mActivePointerId;

    private int mTouchSlop;
    private int mMaxVelocity;
    private int mMinVelocity;
    private int mLastX;
    private int mLastY;


    private boolean mIsDragging;

    private Animator mExpandAndCollapseAnim;

    private GestureDetectorCompat mGestureDetector;

    private Callback mCallback;


    public ItemSlideHelper(Context context, Callback callback) {
        this.mCallback = callback;

        mGestureDetector = new GestureDetectorCompat(context, this);

        ViewConfiguration configuration = ViewConfiguration.get(context);
        mTouchSlop = configuration.getScaledTouchSlop();
        mMaxVelocity = configuration.getScaledMaximumFlingVelocity();
        mMinVelocity = configuration.getScaledMinimumFlingVelocity();
    }

    @Override
    public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
        Log.d(TAG, "onInterceptTouchEvent: " + e.getAction());


        int action =  MotionEventCompat.getActionMasked(e);
        int x = (int) e.getX();
        int y = (int) e.getY();


        if(rv.getScrollState() != RecyclerView.SCROLL_STATE_IDLE){
            if(mTargetView != null){
                //隐藏已经打开
                smoothHorizontalExpandOrCollapse(DEFAULT_DURATION / 2);
                mTargetView = null;
            }

            return false;
        }

        //如果正在运行动画 ,直接拦截什么都不做
        if(mExpandAndCollapseAnim != null && mExpandAndCollapseAnim.isRunning()){
            return true;
        }

        boolean needIntercept =  false;
        switch (action) {
            case MotionEvent.ACTION_DOWN:


                mActivePointerId = MotionEventCompat.getPointerId(e, 0);
                mLastX = (int) e.getX();
                mLastY = (int) e.getY();

                /*
                * 如果之前有一个已经打开的项目,当此次点击事件没有发生在右侧的菜单中则返回TRUE
                * 如果点击的是右侧菜单那么返回FALSE这样做的原因是因为菜单需要响应Onclick
                * */
                if(mTargetView != null){
                    return !inView(x, y);
                }

                //查找需要显示菜单的view;
                mTargetView = mCallback.findTargetView(x, y);

                break;
            case MotionEvent.ACTION_MOVE:

                int deltaX = (x - mLastX);
                int deltaY = (y - mLastY);

                if(Math.abs(deltaY) > Math.abs(deltaX))
                    return false;

                //如果移动距离达到要求,则拦截
                  needIntercept = mIsDragging = mTargetView != null && Math.abs(deltaX) >= mTouchSlop;
                break;

            case MotionEvent.ACTION_CANCEL:
            case MotionEvent.ACTION_UP:
               
                if(isExpanded()){

                    if (inView(x, y)) {
                        Log.d(TAG, "click item");
                    }else{
                        needIntercept = true;
                    }

                    //折叠菜单
                    smoothHorizontalExpandOrCollapse(DEFAULT_DURATION / 2);
                }

                mTargetView = null;
                break;
        }

        return  needIntercept ;
    }



    private boolean isExpanded() {
        return mTargetView != null &&  mTargetView.getScrollX() == getHorizontalRange();
    }

    private boolean isCollapsed() {

        return mTargetView != null && mTargetView.getScrollX() == 0;
    }

    /*
    * 根据targetViewscrollX计算出targetView的偏移,
    * */
    private boolean inView(int x, int y) {

        if (mTargetView == null)
            return false;

        int scrollX = mTargetView.getScrollX();
        int left = mTargetView.getWidth() - scrollX;
        int top = mTargetView.getTop();
        int right = left + getHorizontalRange() ;
        int bottom = mTargetView.getBottom();
        Rect rect = new Rect(left, top, right, bottom);
        return rect.contains(x, y);
    }



    @Override
    public void onTouchEvent(RecyclerView rv, MotionEvent e) {
        Log.d(TAG, "onTouchEvent: " + e.getAction());

        if(mExpandAndCollapseAnim != null && mExpandAndCollapseAnim.isRunning() || mTargetView == null)
            return;

        if (mGestureDetector.onTouchEvent(e)) {
            mIsDragging = false;
            return;
        }

        int x = (int) e.getX();
        int y = (int) e.getY();
        int action =  MotionEventCompat.getActionMasked(e);
        switch (action) {
            case MotionEvent.ACTION_DOWN:

                break;
            case MotionEvent.ACTION_MOVE:
                int deltaX = (int) (mLastX - e.getX());
                if(mIsDragging) {
                    horizontalDrag(deltaX);
                }
                mLastX = x;
                break;

            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:

                 if(mIsDragging){
                    if(!smoothHorizontalExpandOrCollapse(0) && isCollapsed())
                        mTargetView = null;

                    mIsDragging = false;
                 }

                break;
        }


    }

    @Override
    public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {

    }

    /**
     *
     * 根据touch事件来滚动ViewscrollX
     *
     * @param delta
     */
    private void horizontalDrag(int delta) {
        int scrollX = mTargetView.getScrollX();
        int scrollY = mTargetView.getScrollY();
        if ((scrollX + delta) <= 0) {
            mTargetView.scrollTo(0, scrollY);
            return;
        }


        int horRange = getHorizontalRange();
        scrollX += delta;
        if (Math.abs(scrollX) < horRange) {
            mTargetView.scrollTo(scrollX, scrollY);
        } else {
            mTargetView.scrollTo(horRange, scrollY);
        }


    }


    /**
     * 根据当前scrollX的位置判断是展开还是折叠
     *
     * @param velocityX
     *  如果不等于0那么这是一次fling事件,否则是一次ACTION_UP或者ACTION_CANCEL
     */
    private boolean smoothHorizontalExpandOrCollapse(float velocityX) {

        int scrollX = mTargetView.getScrollX();
        int scrollRange = getHorizontalRange();

        if (mExpandAndCollapseAnim != null)
            return false;


        int to = 0;
        int duration = DEFAULT_DURATION;

        if (velocityX == 0) {
            //如果已经展一半,平滑展开
            if (scrollX > scrollRange / 2) {
                to = scrollRange;
            }
        } else {


            if (velocityX > 0)
                to = 0;
            else
                to = scrollRange;

            duration = (int) ((1.f - Math.abs(velocityX) / mMaxVelocity) * DEFAULT_DURATION);
        }

        if(to == scrollX)
            return false;

        mExpandAndCollapseAnim = ObjectAnimator.ofInt(mTargetView, "scrollX", to);
        mExpandAndCollapseAnim.setDuration(duration);
        mExpandAndCollapseAnim.addListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animation) {

            }

            @Override
            public void onAnimationEnd(Animator animation) {
                mExpandAndCollapseAnim = null;
                if (isCollapsed())
                    mTargetView = null;

                Log.d(TAG, "onAnimationEnd");
            }

            @Override
            public void onAnimationCancel(Animator animation) {
                //onAnimationEnd(animation);
                mExpandAndCollapseAnim = null;

                Log.d(TAG, "onAnimationCancel");
            }

            @Override
            public void onAnimationRepeat(Animator animation) {

            }
        });
        mExpandAndCollapseAnim.start();

        return true;
    }




    public  int getHorizontalRange(   ) {
        RecyclerView.ViewHolder viewHolder = mCallback.getChildViewHolder(mTargetView);
        return mCallback.getHorizontalRange(viewHolder);
    }


    @Override
    public boolean onDown(MotionEvent e) {
        return false;
    }

    @Override
    public void onShowPress(MotionEvent e) {

    }

    @Override
    public boolean onSingleTapUp(MotionEvent e) {
        return false;
    }

    @Override
    public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
        return false;
    }

    @Override
    public void onLongPress(MotionEvent e) {

    }

    @Override
    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {

        if(Math.abs(velocityX) > mMinVelocity && Math.abs(velocityX) < mMaxVelocity) {
            if(!smoothHorizontalExpandOrCollapse(velocityX) ) {
                if(isCollapsed())
                    mTargetView = null;
                return true;
            }
        }
        return false;
    }




    public interface Callback {

        int getHorizontalRange(RecyclerView.ViewHolder holder);

        RecyclerView.ViewHolder getChildViewHolder(View childView);

        View findTargetView(float x, float y);

    }
}

下面就到了在适配器中,使用这两个辅助类,进行滑动删除了。

解释一下,看关键的地方,首先这个类实现了上面这个类的中的接口(ItemSlideHelper.Callback),需要实现未实现的方法。其中在getHorizontalRange()方法中

有一个关键的地方:if(holder.itemViewinstanceof LinearLayout)

这句话说的是如果hodler.itemView 是否为LinearLayout的实例。所以你的item的最外部布局如果是LinearLayout的话就写LinearLayout,相同其它也一样。

紧接着:

if(viewGroup.getChildCount() == 2){
                return viewGroup.getChildAt(1).getLayoutParams().width;
            }


这句话说的是子布局的个数为2,就返回第一个子布局的宽度。对于这个例子item布局是由两部分组成的,第一个部分是正常显示的部分,第二个部分就是滑动后显示出来的部分。其它两个方法中的内容ctrl+c即可。

public class BookManagerAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> implements ItemSlideHelper.Callback {
    private static final String TAG="BookManagerAdapter";
    private List<Map<String,Object>> list;
    private Context context;
    private Handler handler;
    private RecyclerView recyclerView;


    public BookManagerAdapter(List<Map<String,Object>> list, Context context, Handler handler){
        this.list=list;
        this.context=context;
        this.handler=handler;
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        return new ItemViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_bookmanager,parent,false));
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        if (holder instanceof ItemViewHolder){
            ItemViewHolder viewHolder= (ItemViewHolder) holder;
            viewHolder.book_name.setText((String)list.get(position).get("book_name"));
            //viewHolder.book_author.setText((String)list.get(position).get("book_author"));
            viewHolder.book_callnum.setText((String)list.get(position).get("book_callnumber"));
            viewHolder.book_count.setText((String)list.get(position).get("book_count")+"");
            viewHolder.book_introduce.setText((String)list.get(position).get("book_introduce"));
        }
    }

    @Override
    public int getItemCount() {
        return list.size();
    }

    @Override
    public int getHorizontalRange(RecyclerView.ViewHolder holder) {
        if(holder.itemView instanceof LinearLayout){
            ViewGroup viewGroup = (ViewGroup) holder.itemView;
            if(viewGroup.getChildCount() == 2){
                return viewGroup.getChildAt(1).getLayoutParams().width;
            }
        }
        return 0;
    }

    @Override
    public RecyclerView.ViewHolder getChildViewHolder(View childView) {
        return recyclerView.getChildViewHolder(childView);
    }

    @Override
    public View findTargetView(float x, float y) {
        return recyclerView.findChildViewUnder(x,y);
    }

    @Override
    public void onAttachedToRecyclerView(RecyclerView recyclerView) {
        super.onAttachedToRecyclerView(recyclerView);
        this.recyclerView = recyclerView;
        recyclerView.addOnItemTouchListener(new ItemSlideHelper(recyclerView.getContext(), this));
    }

    private class ItemViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
        private TextView book_name;
        //private TextView book_author;
        private TextView book_callnum;
        private TextView book_count;
        private TextView book_introduce;
        private TextView book_edit_btn;
        private TextView delete_tv;

        public ItemViewHolder(View itemView) {
            super(itemView);
            book_name = (TextView) itemView.findViewById(R.id.item_bookmanager_bookname);
            //book_author = (TextView) itemView.findViewById(R.id.item_bookmanager_bookauthor);
            book_callnum = (TextView) itemView.findViewById(R.id.item_bookmanager_bookcallnum);
            book_count = (TextView) itemView.findViewById(R.id.item_bookmanager_bookcount);
            book_introduce = (TextView) itemView.findViewById(R.id.item_bookmanager_bookintroduce);
            book_edit_btn = (TextView) itemView.findViewById(R.id.item_bookmanager_tv_btn);
            book_edit_btn.setOnClickListener(this);
            delete_tv= (TextView) itemView.findViewById(R.id.tv_delete);
            delete_tv.setOnClickListener(this);
        }

        @Override
        public void onClick(View v) {
            switch (v.getId()) {
                case R.id.item_bookmanager_tv_btn:
                final EditText edt_count,edt_introduce;
                View view=View.inflate(context,R.layout.bookmanagerdailog,null);
                edt_count = (EditText) view.findViewById(R.id.book_manager_dialog_count);
                edt_introduce = (EditText) view.findViewById(R.id.book_manager_dialog_introduce);
                edt_count.setText(book_count.getText());
                edt_introduce.setText(book_introduce.getText());

                AlertDialog alertDialog=new AlertDialog.Builder(context)
                        .setView(view)
                        .setPositiveButton("确定", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                //获取数量,和介绍
                                new InternetAccess().requestalterbook(handler,(String)list.get(getAdapterPosition()).get("book_id"),
                                        edt_count.getText().toString(),edt_introduce.getText().toString());

                            }
                        })
                        .setNegativeButton("取消", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {

                            }
                        }).create();
                alertDialog.show();
                alertDialog.getWindow().setLayout(600,400);
                    break;
                case R.id.tv_delete:
                    new InternetAccess().Deletebooks((String) list.get(getAdapterPosition()).get("book_id"));
                    list.remove(getAdapterPosition());
                    recyclerView.getAdapter().notifyDataSetChanged();
                    //网络请求删除书籍

                    break;
            }

        }
    }
}


qq:912563071

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值