有人使用RecyclerView找到了一种方法来设置一个onClickListener的项目在RecyclerView? 我想设置一个监听器为每个项目的布局,但这似乎有点太麻烦了 我确信有一种方法让RecyclerView监听onClick事件,但我不能完全弄清楚。
当前回答
基于Jacob Tabak的回答(+1),我能够添加onLongClick监听器:
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
public class RecyclerItemClickListener implements RecyclerView.OnItemTouchListener {
public interface OnItemClickListener {
void onItemClick(View view, int position);
void onItemLongClick(View view, int position);
}
private OnItemClickListener mListener;
private GestureDetector mGestureDetector;
public RecyclerItemClickListener(Context context, final RecyclerView recyclerView, OnItemClickListener listener) {
mListener = listener;
mGestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
@Override
public boolean onSingleTapUp(MotionEvent e) {
return true;
}
@Override
public void onLongPress(MotionEvent e) {
View childView = recyclerView.findChildViewUnder(e.getX(), e.getY());
if (childView != null && mListener != null) {
mListener.onItemLongClick(childView, recyclerView.getChildAdapterPosition(childView));
}
}
});
}
@Override
public boolean onInterceptTouchEvent(RecyclerView view, MotionEvent e) {
View childView = view.findChildViewUnder(e.getX(), e.getY());
if (childView != null && mListener != null && mGestureDetector.onTouchEvent(e)) {
mListener.onItemClick(childView, view.getChildAdapterPosition(childView));
}
return false;
}
@Override
public void onTouchEvent(RecyclerView view, MotionEvent motionEvent) {
}
@Override
public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
}
}
然后你可以这样使用它:
recyclerView.addOnItemTouchListener(new RecyclerItemClickListener(getActivity(), recyclerView, new RecyclerItemClickListener.OnItemClickListener() {
@Override
public void onItemClick(View view, int position) {
// ...
}
@Override
public void onItemLongClick(View view, int position) {
// ...
}
}));
其他回答
查看类似的问题@CommonsWare的评论链接到this,它在viewHolder中实现了OnClickListener接口。
下面是ViewHolder的一个简单例子:
/** Declare global with in adapter class. */
TextView textView;
public static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
private ViewHolder(View itemView) {
super(itemView);
itemView.setOnClickListener(this);
textView = (TextView) view.findViewById(android.R.id.text1);
}
@Override
public void onClick(View view) {
Toast.makeText(view.getContext(), "position = " + getLayoutPosition(), Toast.LENGTH_SHORT).show();
/** Go through each item if you have few items within RecyclerView. */
if (getLayoutPosition() == 0) {
// Do whatever you want here
} else if(getLayoutPosition() == 1) {
// Do whatever you want here
} else if(getLayoutPosition() == 2) {
// Do whatever you want here
}
/** Or you can use For loop if you have long list of items. */
for (int i = 0; i < exampleList.size(); i++) {
// Do whatever you want here
}
}
}
在你的RecyclerView中创建ViewHolder。适配器看起来像这样:
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(parent.getContext())
View view = inflater.inflate(android.R.layout.simple_list_item_1, parent, false);
return new ViewHolder(view);
}
步骤1)编写点击界面
创建一个名为RecyclerViewClickListener.java的接口,并添加以下代码。这里我们声明了两个方法onClick和onLongClick,分别用于标识项目单击和长单击。
package com.androidtutorialshub.recyclerviewtutorial.Helper;
import android.view.View;
public interface RecyclerViewClickListener {
void onClick(View view, int position);
void onLongClick(View view, int position);
}
步骤2)编写项目触摸类
创建一个名为RecyclerViewTouchListener.java的类,并添加以下代码。这里我们编写了检测点击和长按回收器视图项的逻辑。
package com.androidtutorialshub.recyclerviewtutorial.Helper;
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
public class RecyclerViewTouchListener implements RecyclerView.OnItemTouchListener{
private GestureDetector gestureDetector;
private RecyclerViewClickListener clickListener;
public RecyclerViewTouchListener(Context context, final RecyclerView recyclerView, final RecyclerViewClickListener clickListener) {
this.clickListener = clickListener;
gestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
@Override
public boolean onSingleTapUp(MotionEvent e) {
return true;
}
@Override
public void onLongPress(MotionEvent e) {
View child = recyclerView.findChildViewUnder(e.getX(), e.getY());
if (child != null && clickListener != null) {
clickListener.onLongClick(child, recyclerView.getChildPosition(child));
}
}
});
}
@Override
public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
View child = rv.findChildViewUnder(e.getX(), e.getY());
if (child != null && clickListener != null && gestureDetector.onTouchEvent(e)) {
clickListener.onClick(child, rv.getChildPosition(child));
}
return false;
}
@Override
public void onTouchEvent(RecyclerView rv, MotionEvent e) {
}
@Override
public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
}
}
步骤3)定义点击监听器
打开MainActivity.java并更新以下更改。这里onClick()方法将检测点击项目,onLongClick将检测长时间点击项目。
recyclerView.addOnItemTouchListener(new RecyclerViewTouchListener(getApplicationContext(), recyclerView, new RecyclerViewClickListener() {
@Override
public void onClick(View view, int position) {
Toast.makeText(getApplicationContext(), bookList.get(position).getTitle() + " is clicked!", Toast.LENGTH_SHORT).show();
}
@Override
public void onLongClick(View view, int position) {
Toast.makeText(getApplicationContext(), bookList.get(position).getTitle() + " is long pressed!", Toast.LENGTH_SHORT).show();
}
}));
欲了解更多信息或下载源代码:http://www.androidtutorialshub.com/android-recyclerview-click-listener-tutorial/
很简单,添加这个类:
public class OnItemClickListener implements View.OnClickListener {
private int position;
private OnItemClickCallback onItemClickCallback;
public OnItemClickListener(int position, OnItemClickCallback onItemClickCallback) {
this.position = position;
this.onItemClickCallback = onItemClickCallback;
}
@Override
public void onClick(View view) {
onItemClickCallback.onItemClicked(view, position);
}
public interface OnItemClickCallback {
void onItemClicked(View view, int position);
}
}
获取一个'OnItemClickCallback'接口实例,并把它放在你的activity或fragment中:
private OnItemClickListener.OnItemClickCallback onItemClickCallback = new OnItemClickListener.OnItemClickCallback() {
@Override
public void onItemClicked(View view, int position) {
}
};
然后,将这个回调传递给你的recyclerView:
recyclerView.setAdapter(new SimpleStringRecyclerViewAdapter(Arrays.asList("1", "2", "3"), onItemClickCallback));
最后,这将是你的适配器:
public class SimpleStringRecyclerViewAdapter extends RecyclerView.Adapter<SimpleStringRecyclerViewAdapter.ViewHolder> {
private List<String> mValues;
private OnItemClickListener.OnItemClickCallback onItemClickCallback;
public SimpleStringRecyclerViewAdapter(List<String> items, OnItemClickListener.OnItemClickCallback onItemClickCallback) {
mValues = items;
this.onItemClickCallback = onItemClickCallback;
}
public static class ViewHolder extends RecyclerView.ViewHolder {
public final TextView mTextView;
public ViewHolder(View view) {
super(view);
mTextView = (TextView) view.findViewById(R.id.txt_title);
}
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item, parent, false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
holder.mTextView.setText(mValues.get(position));
holder.mTextView.setOnClickListener(new OnItemClickListener(position, onItemClickCallback));
}
@Override
public int getItemCount() {
return mValues.size();
}
}
这里有一个策略,它给出了一个类似于ListView实现的结果,因为你可以在活动或片段级别而不是适配器或ViewHolder级别定义侦听器。它还定义了一些抽象类,这些抽象类负责适配器和持有者的大量样板工作。
抽象类
首先,定义一个抽象Holder,它扩展了RecyclerView。并定义了一个泛型数据类型T,用于将数据绑定到视图。bindViews方法将由一个子类实现,用于将数据映射到视图。
public abstract class Holder<T> extends RecyclerView.ViewHolder {
T data;
public Holder(View itemView) {
super(itemView);
}
public void bindData(T data){
this.data = data;
bindViews(data);
}
abstract protected void bindViews(T data);
}
同样,创建一个抽象适配器,扩展RecyclerView.Adapter<Holder<T>>。这定义了3个接口方法中的2个,子类将需要实现最后一个onViewHolderCreated方法。
public abstract class Adapter<T> extends RecyclerView.Adapter<Holder<T>> {
List<T> list = new ArrayList<>();
@Override
public void onBindViewHolder(Holder<T> holder, int position) {
holder.bindData(list.get(position));
}
@Override
public int getItemCount() {
return list.size();
}
public T getItem(int adapterPosition){
return list.get(adapterPosition);
}
}
具体类
现在创建一个扩展Holder的新具体类。该方法只需定义视图并处理绑定。这里我使用ButterKnife库,但请随意使用itemView.findViewById(…)方法代替。
public class PersonHolder extends Holder<Person>{
@Bind(R.id.firstname) TextView firstname;
@Bind(R.id.lastname) TextView lastname;
public PersonHolder(View view){
super(view);
ButterKnife.bind(this, view);
}
@Override
protected void bindViews(Person person) {
firstname.setText(person.firstname);
lastname.setText(person.lastname);
}
}
最后,在持有RecyclerView的Activity或Fragment类中,你会有这样的代码:
// Create adapter, this happens in parent Activity or Fragment of RecyclerView
adapter = new Adapter<Person>(){
@Override
public PersonHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.layout_person_view, parent, false);
PersonHolder holder = new PersonHolder(v);
v.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
int itemPos = holder.getAdapterPosition();
Person person = getItem(itemPos);
// do something with person
EventBus.getDefault().postSticky(new PersonClickedEvent(itemPos, person));
}
});
return holder;
}
};
我知道有很多答案,但我想我也可以提供我的实现。(完整的细节可以在我回答的另一个问题中找到)。
所以,要添加一个点击监听器,你的内部ViewHolder类需要实现View.OnClickListener。这是因为你将设置一个OnClickListener到ViewHolder的构造函数的itemView参数。让我来告诉你我的意思:
public class ExampleClickViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
TextView text1, text2;
ExampleClickViewHolder(View itemView) {
super(itemView);
// we do this because we want to check when an item has been clicked:
itemView.setOnClickListener(this);
// now, like before, we assign our View variables
title = (TextView) itemView.findViewById(R.id.text1);
subtitle = (TextView) itemView.findViewById(R.id.text2);
}
@Override
public void onClick(View v) {
// The user may not set a click listener for list items, in which case our listener
// will be null, so we need to check for this
if (mOnEntryClickListener != null) {
mOnEntryClickListener.onEntryClick(v, getLayoutPosition());
}
}
}
唯一需要添加的其他东西是适配器的自定义接口和setter方法:
private OnEntryClickListener mOnEntryClickListener;
public interface OnEntryClickListener {
void onEntryClick(View view, int position);
}
public void setOnEntryClickListener(OnEntryClickListener onEntryClickListener) {
mOnEntryClickListener = onEntryClickListener;
}
这样,新的支持单击的适配器就完成了。
现在,让我们用它…
ExampleClickAdapter clickAdapter = new ExampleClickAdapter(yourObjects);
clickAdapter.setOnEntryClickListener(new ExampleClickAdapter.OnEntryClickListener() {
@Override
public void onEntryClick(View view, int position) {
// stuff that will happen when a list item is clicked
}
});
这基本上就是设置普通适配器的方法,除了使用您创建的setter方法来控制当用户单击特定列表项时要做什么。
你也可以看看我在GitHub上做的一组关于Gist的例子:
https://gist.github.com/FarbodSalamat-Zadeh/7646564f48ee708c1582c013e1de4f07
推荐文章
- 警告: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++ ?