android RecyclerView 长按之后滑动手指多选

明天有风吹 / 2024-07-09 / 原文

关键函数与类

  • LinearLayoutManager.canScrollHorizontally()
  • LinearLayoutManager.canScrollVertically()
  • RecyclerView.OnItemTouchListener

核心代码

mCanRecyclerViewScroll = true;

recyclerView.setLayoutManager(new LinearLayoutManager(getContext(), LinearLayoutManager.VERTICAL, false) {
    @Override
    public boolean canScrollHorizontally() {
        return mCanRecyclerViewScroll && super.canScrollHorizontally();
    }

    @Override
    public boolean canScrollVertically() {
        return mCanRecyclerViewScroll && super.canScrollVertically();
    }
});

recyclerView.addOnItemTouchListener(new RecyclerView.OnItemTouchListener() {
    boolean is_down = false;
    @Override
    public boolean onInterceptTouchEvent(@NonNull RecyclerView rv, @NonNull MotionEvent e) {
        // Touch with many fingers, don't handle
        if (e.getPointerCount() > 1) return false;

        switch (e.getAction()) {
            case MotionEvent.ACTION_DOWN:
                is_down = true;
                rv.postDelayed(()->{
                    if (!is_down) return;
                    mCanRecyclerViewScroll = false;
                    View viewUnder = rv.findChildViewUnder(e.getX(), e.getY());
                    if (viewUnder == null) return;
                    RecyclerView.ViewHolder viewHolder = rv.findContainingViewHolder(viewUnder);
                    if (viewHolder == null) return;
                    Rect rect = new Rect();
                    if (viewHolder.itemView.getGlobalVisibleRect(rect) && rect.contains((int)e.getRawX(), (int)e.getRawY())) {
                        viewHolder.itemView.setBackgroundColor(Color.CYAN);
                    }
                }, 500);
                break;
            case MotionEvent.ACTION_UP:
                is_down = false;
                break;
            case MotionEvent.ACTION_MOVE:
                return !mCanRecyclerViewScroll;
            default:
                break;
        }
        return false;
    }

    @Override
    public void onTouchEvent(@NonNull RecyclerView rv, @NonNull MotionEvent e) {
        View viewUnder = rv.findChildViewUnder(e.getX(), e.getY());
        if (viewUnder == null) return;
        RecyclerView.ViewHolder viewHolder = rv.findContainingViewHolder(viewUnder);
        if (viewHolder == null) return;
        Rect rect = new Rect();
        if (viewHolder.itemView.getGlobalVisibleRect(rect) && rect.contains((int)e.getRawX(), (int)e.getRawY())) {
            viewHolder.itemView.setBackgroundColor(Color.CYAN);
        }
    }

    @Override
    public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {}
});

参考链接

How to multi-select using drag gesture in RecyclerView ?