简体   繁体   中英

How to click through a recyclerview?

First of all I am struggling with this issue for a long time. I don't know how to figure out things, so I followed these steps and tutorials with no luck.

  1. Click through recycler view empty space
  2. Click through a recyclerview list item

and a bunch of questions on StackOverflow. I wrote my own code also. May be I am doing something silly but am not able to figure it out.

mRecyclerView.setOnTouchListener((v, event) -> {
    RectF rectf = new RectF((int) event.getX(), 
                            (int) event.getY(), 
                            0, 0);
    boolean contains = getCenter(mHeaderPopUp).contains(rectf);
    if (contains) {
        Toast.makeText(mContext, "Clicked", Toast.LENGTH_SHORT).show();
    }
    return false;
});

private RectF getCenter(View view) {
    Rect rect = new Rect();
    view.getLocalVisibleRect(rect);
    RectF dimens = new RectF((rect.left + rect.width() / 2), 
                             (int) (rect.top + rect.height() / 2),
                             0, 0);
    return dimens;
}

So now I have tried all of these things but I am not able to click through recyclerview to the view which is below recyclerview which you can see in the below image. recyclerview overlays all the views on the screen and I need to pass the click to below recyclerview I don't want to put those views above the recyclerview as when you scroll recyclerview it will be animatated and would cover all the views with its items. Thanks in advance. This is the image

I think I found it.

Use recycler.setLayoutFrozen(true);

You can still assign onClickListeners to your items, but if you don't, the click will go through.

From the source code of RecyclerView.java :

@Override
public boolean onTouchEvent(MotionEvent e) {
    if (mLayoutFrozen || mIgnoreMotionEventTillDown) {
        return false; // <= This will prevent the RecyclerView from getting the MotionEvent
    }
...
}

https://android.googlesource.com/platform/frameworks/support/+/refs/heads/master/v7/recyclerview/src/android/support/v7/widget/RecyclerView.java#2795

Hello I found an answer. I have card below RecyclerView and recyclerView has padding from left and I set clipToFading=false. To make card below recyclerView clickable I created RecyclerTouch event class and when clicked childView is null it means it is outside childs and open space and I give touch event to my card. Here is Code

public class RecyclerTouchEvent implements RecyclerView.OnItemTouchListener {
    private GestureDetector gestureDetector;
    ClickListener clickListener;

    public RecyclerTouchEvent(Context context, final RecyclerView recyclerView, final ClickListener clickListener) {
        this.clickListener = clickListener;
        gestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
            @Override
            public boolean onSingleTapUp(MotionEvent e) {

                return super.onSingleTapUp(e);
            }

            @Override
            public void onLongPress(MotionEvent e) {
                super.onLongPress(e);
            }

        });

    }

    @Override
    public boolean onInterceptTouchEvent(final RecyclerView rv, MotionEvent e) {
        final View childView = rv.findChildViewUnder(e.getX(), e.getY());


        if (childView != null && clickListener != null) {
            clickListener.onClick(childView);
        }else if (childView==null&&clickListener!=null){
            clickListener.onOutsideClick(e);
        }

        return false;
    }

    @Override
    public void onTouchEvent(RecyclerView rv, MotionEvent motionEvent) {

    }

    @Override
    public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {

    }
}

public static interface ClickListener {
    public void onClick(View view);
    public void onOutsideClick(MotionEvent event);
}

AND

recyclerViewLends.addOnItemTouchListener(new RecyclerTouchEvent(getContext(), recyclerViewLends, new ClickListener() {
            @Override
            public void onClick(View view) {

            }

            @Override
            public void onOutsideClick(MotionEvent e) {
                rippleLayoutAddLend.dispatchTouchEvent(e);
            }
        }));

rippleLayoutAddLend is a View below recyclerView that has to be clicked

I had situation when my RecyclerView header item is fully transparent and need catch click behind it.

Inside Activity function:

override fun dispatchTouchEvent(ev: MotionEvent?): Boolean

I call extension function RecyclerView.suppressOnHeader :

/**
 * If [onView] returns true -> it means what need skip this touch action for [RecyclerView]:
 * - Set true for [RecyclerView.suppressLayout], that makes list not scrollable and 
 *   transparent for clicking.
 *
 * If [onView] returns false -> it means what need vice versa make [RecyclerView] 
 * scrollable  and not transparent for clicking:
 * - Set false for [RecyclerView.suppressLayout], turn on touch events and scrolling for list.
 * - Need call [RecyclerView.onInterceptTouchEvent], this need for reset key
 *   [RecyclerView.mIgnoreMotionEventTillDown], which was setup when we call
 *   [RecyclerView.suppressLayout]. If skip this step when first [RecyclerView] click
 *   will be ignored. For information see [RecyclerView.onTouchEvent].
 * - And in the end call [RecyclerView.onTouchEvent], like we make a touch event.
 */
fun RecyclerView.suppressOnHeader(ev: MotionEvent?) {
    if (ev?.action != MotionEvent.ACTION_DOWN) return

    val holderView = findViewHolderForAdapterPosition(0)?.itemView

    if (ev.onView(holderView)) {
        if (!isLayoutSuppressed) {
           suppressLayout(true)
        }
    } else {
        if (isLayoutSuppressed) {
            suppressLayout(false)
            onInterceptTouchEvent(ev)
            onTouchEvent(ev)
        }
    }
}

fun MotionEvent?.onView(view: View?): Boolean {
    if (view == null || this == null) return false

    return Rect().apply {
        view.getGlobalVisibleRect(this)
    }.contains(rawX.toInt(), rawY.toInt())
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM