如何点击回收者视图?

时间:2017-07-15 08:33:36

标签: android android-layout android-recyclerview android-view

首先,我正在努力解决这个问题很长一段时间。我不知道如何弄清楚事情,所以我没有运气就按照这些步骤和教程。

  1. Click through recycler view empty space
  2. Click through a recyclerview list item
  3. 和StackOverflow上的一堆问题。我也写了自己的代码。可能是我在做一些愚蠢的事情,但我无法弄明白。

    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;
    }
    

    所以现在我已经尝试了所有这些东西但是我无法通过recyclerview点击在recyclerview下方的视图,您可以在下图中看到。 recyclerview覆盖屏幕上的所有视图,我需要将点击传递给recyclelerview下面我不想将这些视图放在recyclerview上方,因为当您滚动recyclelerview时它会被动画化并覆盖所有视图及其项目。 提前致谢。 This is the image

3 个答案:

答案 0 :(得分:4)

我想我找到了它。

使用recycler.setLayoutFrozen(true);

您仍然可以将onClickListeners分配给您的项目,但如果不这样做,则点击将会完成。

来自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

答案 1 :(得分:3)

您好我找到了答案。 我在RecyclerView下面有卡片,recyclelerView从左边有填充,我设置了clipToFading = false。 为了使卡片在recycler下方可点击,我创建了RecyclerTouch事件类,当点击了childView为null时,它意味着它在孩子和开放空间之外,我给我的卡片提供触摸事件。 这是代码

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是一个必须单击的recyclelerView下面的视图

答案 2 :(得分:0)

当我的 RecyclerView 标题项完全透明并且需要在其后面点击时,我遇到过这种情况。

内部 Activity 函数:

override fun dispatchTouchEvent(ev: MotionEvent?): Boolean

我调用扩展函数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())
}