有人使用RecyclerView找到了一种方法来设置一个onClickListener的项目在RecyclerView? 我想设置一个监听器为每个项目的布局,但这似乎有点太麻烦了 我确信有一种方法让RecyclerView监听onClick事件,但我不能完全弄清楚。
当前回答
以下是我所做的。这个解决方案同时支持onClick和onLongClick在两个RecyclerView项目和视图内的RecyclerView项目(内部视图)。
我在我选择的视图上标记viewHolder:
public RecyclerViewAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_item, null);
ViewHolder viewHolder = new ViewHolder(itemView);
itemView.setOnClickListener( this);
itemView.setOnLongClickListener(this);
viewHolder.imageIV.setOnClickListener(this);
viewHolder.imageIV.setOnLongClickListener(this);
viewHolder.imageIV.setTag(viewHolder);
itemView.setTag(viewHolder);
return viewHolder;
}
我使用holder.getPosition()在onClick()方法中检索位置(onLongClick类似):
public void onClick(View view) {
ViewHolder holder = (ViewHolder) view.getTag();
int position = holder.getPosition();
if (view.getId() == holder.imageIV.getId()){
Toast.makeText(context, "imageIV onClick at" + position, Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(context, "RecyclerView Item onClick at " + position, Toast.LENGTH_SHORT).show();
}
}
带有getChildPosition的变体也可以工作。请注意,对于内部视图,在onClick()中使用:
int position = recyclerView.getChildPosition((View)view.getParent());
在我看来,这个解决方案的优点是,当一个人点击图像,只有onclick()图像侦听器被调用,而当我结合Jacob的解决方案为一个RecyclerView项目视图和我的解决方案为内部视图的RecyclerView项目视图onclick()也被调用(当点击图像)。
其他回答
我们可以使用Java弱引用来实现这一点。 从语义上讲,视图持有者应该响应click事件或将其委托给正确的响应器。
我们的目标:
Viewholder应该对响应事件的类一无所知,除非它实现了某个接口。 点击处理程序应该得到被点击的视图在RecyclerView中的位置。 我们应该能够辨别视图持有人中单击了哪个视图。 保持所有组件之间的松散耦合,不要造成任何保留周期。
步骤:
Create an interface to handle click responses. Implement this interface in the Activity that will handle the click. Add a member variable in the RecyclerView Adapter to hold the Weak Reference and a constructor that sets it. Do the same in the RecyclerView ViewHolder and add a member variable to keep track of position. Set your on click listeners on any view you'd like in the ViewHolder, then callback to the responder to handle them. Change your onBindViewHolder method to set the position when binding. Pass the responder down to the ViewHolder. In the responder, you can now use getId() on the view to figure out which view was clicked.
这里是一个要点,这样你就可以看到它们是如何组合在一起的: RecyclerView点击处理
这对我来说很管用。将OnClickListener附加到onBindView。我真的不知道这是否会影响性能,但它似乎用很少的代码就能很好地工作。
public void onBindViewHolder(ViewHolder holder, final int position) {
holder.view.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Toast.makeText(context, "Recycle Click" + position, Toast.LENGTH_SHORT).show();
}
});
}
别白费力气了!这个特定用例的代码包含在Android Studio附带的Master/Detail Flow启动器项目中。
从Android Studio选择:
文件>新建>新建项目.... 在Phone and Tablet选项卡中选择如下所示的Master/Detail Flow。
用Kotlin或Java创建项目。 利润。
我不会在这里包括谷歌的ootb演示项目的代码,但我会概述谷歌提供的示例中的主要设计方法:
the item OnClickListener is created ONLY ONCE, and is assigned to a field in your RecyclerView.Adapter implementation. in the onBindViewHolder() you should set the same, pre-created onClickListener object on your ViewHolder instance with holder.itemView.setOnClickListener(mOnClickListener) (AVOID creating a new instance on every method call!); if you need to capture clicks on some specific elements inside the ViewHolder then extend ViewHolder and expose the elements you need as fields so that you can attach whatever listeners you need in onBindViewHolder() — and once again, do NOT re-create the listeners on every method call — initialise them as instance fields and attach them as needed. you can use .setTag() in order to pass state to your viewHolder, e.g. holder.itemView.setTag(mValues.get(position)); as used in the demo.
在ViewHolder中设置点击监听器,如下所示:
public class MyViewHolder extends RecyclerView.ViewHolder {
public TextView title, year, genre;
public MyViewHolder(View view) {
super(view);
title = (TextView) view.findViewById(R.id.title);
genre = (TextView) view.findViewById(R.id.genre);
year = (TextView) view.findViewById(R.id.year);
view.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(context, ""+getAdapterPosition(), Toast.LENGTH_SHORT).show();
}
});
}
}
不幸的是,RecyclerView缺少ListView内置的几个功能。 例如,添加OnItemClickListener的能力,当一个项目被单击时触发。 RecyclerView允许你在适配器中设置一个OnClickListener,但是传递那个点击 从你的调用代码,到适配器,再到ViewHolder,监听器是复杂的 要捕捉一个简单的项目单击。
public class ItemClickSupport {
private final RecyclerView mRecyclerView;
private OnItemClickListener mOnItemClickListener;
private OnItemLongClickListener mOnItemLongClickListener;
private View.OnClickListener mOnClickListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mOnItemClickListener != null) {
RecyclerView.ViewHolder holder = mRecyclerView.getChildViewHolder(v);
mOnItemClickListener.onItemClicked(mRecyclerView, holder.getAdapterPosition(), v);
}
}
};
private View.OnLongClickListener mOnLongClickListener = new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
if (mOnItemLongClickListener != null) {
RecyclerView.ViewHolder holder = mRecyclerView.getChildViewHolder(v);
return mOnItemLongClickListener.onItemLongClicked(mRecyclerView, holder.getAdapterPosition(), v);
}
return false;
}
};
private RecyclerView.OnChildAttachStateChangeListener mAttachListener
= new RecyclerView.OnChildAttachStateChangeListener() {
@Override
public void onChildViewAttachedToWindow(View view) {
if (mOnItemClickListener != null) {
view.setOnClickListener(mOnClickListener);
}
if (mOnItemLongClickListener != null) {
view.setOnLongClickListener(mOnLongClickListener);
}
}
@Override
public void onChildViewDetachedFromWindow(View view) {
}
};
private ItemClickSupport(RecyclerView recyclerView) {
mRecyclerView = recyclerView;
mRecyclerView.setTag(R.id.item_click_support, this);
mRecyclerView.addOnChildAttachStateChangeListener(mAttachListener);
}
public static ItemClickSupport addTo(RecyclerView view) {
ItemClickSupport support = (ItemClickSupport) view.getTag(R.id.item_click_support);
if (support == null) {
support = new ItemClickSupport(view);
}
return support;
}
public static ItemClickSupport removeFrom(RecyclerView view) {
ItemClickSupport support = (ItemClickSupport) view.getTag(R.id.item_click_support);
if (support != null) {
support.detach(view);
}
return support;
}
public ItemClickSupport setOnItemClickListener(OnItemClickListener listener) {
mOnItemClickListener = listener;
return this;
}
public ItemClickSupport setOnItemLongClickListener(OnItemLongClickListener listener) {
mOnItemLongClickListener = listener;
return this;
}
private void detach(RecyclerView view) {
view.removeOnChildAttachStateChangeListener(mAttachListener);
view.setTag(R.id.item_click_support, null);
}
public interface OnItemClickListener {
void onItemClicked(RecyclerView recyclerView, int position, View v);
}
public interface OnItemLongClickListener {
boolean onItemLongClicked(RecyclerView recyclerView, int position, View v);
}
}
您还需要定义R.id。使用ids.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<item name="item_click_support" type="id" />
</resources>
结果代码点击侦听器现在看起来像这样:
ItemClickSupport.addTo(mRecyclerView).setOnItemClickListener(new ItemClickSupport.OnItemClickListener() {
@Override
public void onItemClicked(RecyclerView recyclerView, int position, View v) {
// do it
}
});
关于recyclerview点击的简要说明,请看看这个littlerobots_blog
推荐文章
- 警告:API ' variable . getjavacompile()'已过时,已被' variable . getjavacompileprovider()'取代
- 安装APK时出现错误
- 在流中使用Java 8 foreach循环移动到下一项
- 访问限制:'Application'类型不是API(必需库rt.jar的限制)
- 用Java计算两个日期之间的天数
- 碎片中的onCreateOptionsMenu
- 如何配置slf4j-simple
- 在Jar文件中运行类
- 带参数的可运行?
- TextView粗体通过XML文件?
- 如何使线性布局的孩子之间的空间?
- 我如何得到一个字符串的前n个字符而不检查大小或出界?
- 我可以在Java中设置enum起始值吗?
- Java中的回调函数
- c#和Java中的泛型有什么不同?和模板在c++ ?