setOnClickListener for recyclerView无法正常工作

时间:2017-07-25 09:02:34

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

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

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

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

7 个答案:

答案 0 :(得分:2)

尝试扩展RecyclerView和覆盖onInterceptTouchEvent使其始终返回。然后使用OnTouch代替OnClickL... 以下是一些代码。

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

答案 1 :(得分:1)

  

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

为什么您认为点击RecyclerView本身? 很可能RecyclerView的项目吞下了触摸事件,因此无法访问RecyclerView。您可以让RecyclerView的孩子无法点击,然后有机会回复点击事件的下一个项目就是RecyclerView

答案 2 :(得分:0)

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

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

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

私人决赛名单项目; private final OnItemClickListener listener;

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

答案 3 :(得分:0)

因为还没有人回答实际的问题。

我的解决方案是使用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顶部放置一个空视图,以接收点击次数

答案 4 :(得分:0)

只需使用setOnTouchListener代替setOnClickListener

对我有用。 。

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

答案 5 :(得分:0)

此代码有效:

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

答案 6 :(得分:0)

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通常在屏幕上的一次轻击中被多次调用,因此我们应该在上一次触摸事件之后仅运行一次代码。此外,业务逻辑应该进入OnClickListener所调用的performClick()(随后返回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
    }
});