【问题标题】:How to click through a recyclerview?如何点击一个recyclerview?
【发布时间】:2017-07-15 08:33:35
【问题描述】:

首先,我在这个问题上苦苦挣扎了很长时间。我不知道如何弄清楚事情,所以我按照这些步骤和教程没有运气。

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

还有一堆关于 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 覆盖屏幕上的所有视图,我需要将点击传递到下方的 recyclerview 我不想将这些视图放在 recyclerview 上方,因为当您滚动 recyclerview 时,它将被动画化,并会用它的项目覆盖所有视图。 提前致谢。 This is the image

【问题讨论】:

  • 将两者都放入一个RelativeLayout 并为您的RecyclerView 定义一个上边距。那么RecyclerView上面的图片就可以点击了
  • 我猜你没有得到我的问题

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


【解决方案1】:

我想我找到了。

使用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

【讨论】:

  • recycler.setLayoutFrozen(true) 之后,recyclerView 无法滚动。太可怕了
  • 就我而言,我不需要它来滚动。多谢。我的recyclerview 位于另一个recyclerview 之上,我希望它忽略点击。这行得通。
【解决方案2】:

您好,我找到了答案。 我在 RecyclerView 下方有卡,recyclerView 从左侧有填充,我设置了 clipToFading=false。 为了使 recyclerView 下面的卡片可点击,我创建了 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);
}

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

            }

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

rippleLayoutAddLend 是recyclerView下面的一个View,必须点击

【讨论】:

  • 有很多不必要的代码,但是解决方法是对的!
【解决方案3】:

当我的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())
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-04-24
    • 2017-07-30
    • 1970-01-01
    • 1970-01-01
    • 2017-08-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多