【问题标题】:setOnClickListener for recyclerView not workingrecyclerView 的 setOnClickListener 不起作用
【发布时间】:2026-01-25 06:55:01
【问题描述】:

对于RecyclerView如果没有任何项目,则点击RecyclerView作品, 但如果它有项目点击RecyclerView 不起作用。 小心我的意思是点击RecyclerView 而不是RecyclerView 的项目

recyclerView.setOnClickListener(view -> {Timber.d("recyclerView clicked");});

我如何设置RecyclerView 可点击,即使它上面有项目。

【问题讨论】:

  • 你的意思是点击特定的回收站视图行??
  • @sumit,不,我的意思是 recyclerView 而不是它的 items 和 rows 。像我想在 recyclerView 上设置点击监听器的任何其他视图一样
  • @YBDevi ,其实是另一种观点,不过这样不行!
  • 那么只有你可以使用 OnTouchListener,因为如果你点击回收站视图,它只会被视为项目点击。

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


【解决方案1】:

尝试扩展RecyclerView 并覆盖onInterceptTouchEvent。也让它总是返回 true。然后使用OnTouch 而不是OnClickListener 这是一些代码。

public class MyRecyclerView extends RecyclerView {
    public MyRecyclerView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent e) {
        return true;
    }
}

Activity.class

recyclerView.setOnTouchListener(new View.OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
 Toast.makeText(MainActivity.this,"RecyclerView",Toast.LENGTH_SHORT).show();
            return false;
        }
    });

【讨论】:

  • 是的,谢谢,我认为这可行,但我正在寻找另一种解决方案
【解决方案2】:

TL;DR Java

recyclerView.setOnTouchListener(new OnTouchListener() {
    @Override
    public boolean onTouch(View view, MotionEvent motionEvent) {
        if (motionEvent.getAction() == MotionEvent.ACTION_UP)
            return view.performClick();
        else
            return false;
    }
});

recyclerView.setOnClickListener(new OnClickListener() {
    @Override
    public void onClick(View view) {
        // do something
    }
});

TL;DR Kotlin

recyclerView.setOnTouchListener { view, motionEvent ->
    if (motionEvent.action == MotionEvent.ACTION_UP)
        view.performClick()
    else
        false
}

recyclerView.setOnClickListener { view ->
    // do something
}

说明(Java)

当用户触摸屏幕时,触发最顶层视图的OnTouchListener。其目的是检测手势(点击、长按、滑动等)并调用相应的处理程序。例如,一个简单的点击应该会导致调用OnClickListener

现在,出于某种原因,RecyclerView 不这样做(至少它不注意点击手势)- 可能是因为开发人员不打算将 RecyclerView 作为一个整体点击。

所以,我们自己实现了OnTouchListener。最简单的方法是在 OnTouchListener 本身中实现点击逻辑并返回 true 以防止事件在视图层次结构中进一步向上传播:

recyclerView.setOnTouchListener(new OnTouchListener() {
    @Override
    public boolean onTouch(View view, MotionEvent motionEvent) {
        // do something
        return true
    }
});

但是,由于OnTouchListener 通常在单击屏幕时会被多次调用,因此我们应该在最后一次触摸事件之后只运行一次代码。此外,业务逻辑应该进入performClick()调用的OnClickListener(之后返回true):

recyclerView.setOnTouchListener(new OnTouchListener() {
    @Override
    public boolean onTouch(View view, MotionEvent motionEvent) {
        if (motionEvent.getAction() == MotionEvent.ACTION_UP)
            return view.performClick();
        else
            return false;
    }
});

recyclerView.setOnClickListener(new OnClickListener() {
    @Override
    public void onClick(View view) {
        // do something
    }
});

【讨论】:

    【解决方案3】:

    只需使用setOnTouchListener 而不是setOnClickListener

    它对我有用。 . .

    recyclerView.setOnTouchListener(new View.OnTouchListener() {
                @Override
                public boolean onTouch(View view, MotionEvent motionEvent) {
                    //Do anyThing you need
                    return false;
                }
            });
    

    【讨论】:

    • 这个解决方案的有趣之处在于 MotionEvent.ACTION_DOWN 永远不会被调用,因此如果发生 ACTION_MOVE 事件就会调用 ACTION_UP
    【解决方案4】:

    但如果有项目点击 RecyclerView 不起作用

    为什么您认为您正在点击RecyclerView 本身? 很可能RecyclerView 的项目吞下了触摸事件,因此它不会到达RecyclerView。您可以使RecyclerView 的子项不可点击,那么下一个有机会响应点击事件的项目将是RecyclerView

    【讨论】:

    • 尝试为项目 xml 设置可点击和可聚焦的 false,但它没有帮助向 RecyclerView 提供点击事件以作为视图执行。
    【解决方案5】:

    您首先需要一个指定侦听器行为的接口。在此示例中,有一个名为 ContentItem 的示例模型,因此单击将返回该类型的项目:

    public interface OnItemClickListener {
        void onItemClick(ContentItem item);
    }
    

    构造函数将接收一个实现此接口的对象,以及要渲染的项目:

    私有最终列表项; 私有最终 OnItemClickListener 监听器;

    public ContentAdapter(List<ContentItem> items, OnItemClickListener listener) {
        this.items = items;
        this.listener = listener;
    }
    

    您也可以创建一个 setOnItemClickListener 方法并以这种方式分配它。现在,在 onBindViewHolder 中,ViewHolder 将在自定义绑定方法中接收构造函数:

    @Override public void onBindViewHolder(ViewHolder holder, int position) {
        holder.bind(items.get(position), listener);
    }
    

    这就是这个绑定方法的样子:

    public void bind(final ContentItem item, final OnItemClickListener listener) {
        ...
        itemView.setOnClickListener(new View.OnClickListener() {
            @Override public void onClick(View v) {
                listener.onItemClick(item);
            }
        });
    }
    

    通过创建一个新的适配器和侦听器来在您需要时使用它,以在单击项目时实现该行为。一个简单的例子:

    recycler.setAdapter(new ContentAdapter(items, new ContentAdapter.OnItemClickListener() {
        @Override public void onItemClick(ContentItem item) {
            Toast.makeText(getContext(), "Item Clicked", Toast.LENGTH_LONG).show();
        }
    }));
    

    【讨论】:

    • @MehrdadFaraji android 不会给你 onItemClick 和列表视图控件一样的,你必须手动实现。
    【解决方案6】:

    因为还没有人回答实际问题本身..

    我的解决方案是使用 ConstraintLayout 在 RecyclerView 顶部放置一个空视图,例如

        <androidx.recyclerview.widget.RecyclerView
                app:layout_constraintTop_toBottomOf="@+id/toolbar"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintEnd_toEndOf="parent"
                android:id="@+id/recycler_view"
                android:layout_width="match_parent"
                android:layout_height="0dp">
    
        </androidx.recyclerview.widget.RecyclerView>
    
        <View
                android:id="@+id/touch_overlay"
                android:layout_width="0dp"
                android:layout_height="0dp"
                app:layout_constraintTop_toTopOf="@+id/recycler_view"
                app:layout_constraintStart_toStartOf="@+id/recycler_view"
                app:layout_constraintEnd_toEndOf="@+id/recycler_view"
                app:layout_constraintBottom_toBottomOf="@+id/recycler_view"/>
    

    然后我会在 touch_overlay 上设置 onClickListener,它会按预期工作。

    在 Java/Kotlin 方面正如预期的那样

        binding.touchOverlay.setOnClickListener {
            Toast.makeText(context, "clicked recyclerView", Toast.LENGTH_LONG).show()
        }
    

    另一方面,更轻量级的解决方案,尤其是在不使用 ConstraintLayout 时,是使用 FrameLayout,然后在 RecyclerView 顶部放置一个空 View 以接收点击

    【讨论】:

      【解决方案7】:

      此代码有效:

        recycle.setOnTouchListener { v, event ->
                      if(event.action == MotionEvent.ACTION_UP){
                          onClickListener.onClick(v)
                      }
                      false
                  }
      

      【讨论】: