RecyclerView onClick

是否有人使用RecyclerView找到了一种方法来将onClickListener设置为RecyclerView中的项目? 我想设置一个监听器为每个项目的布局,但这似乎有点太麻烦了 我相信有一种方法可以让RecyclerView监听onClick事件,但我不太清楚
771677 次浏览

由于API已经发生了根本性的变化,如果您为每个项目创建OnClickListener,我也不会感到惊讶。不过也没那么麻烦。在RecyclerView.Adapter<MyViewHolder>的实现中,你应该有:

private final OnClickListener mOnClickListener = new MyOnClickListener();


@Override
public MyViewHolder onCreateViewHolder(final ViewGroup parent, final int viewType) {
View view = LayoutInflater.from(mContext).inflate(R.layout.myview, parent, false);
view.setOnClickListener(mOnClickListener);
return new MyViewHolder(view);
}

onClick方法:

@Override
public void onClick(final View view) {
int itemPosition = mRecyclerView.getChildLayoutPosition(view);
String item = mList.get(itemPosition);
Toast.makeText(mContext, item, Toast.LENGTH_LONG).show();
}

查看类似的问题 @CommonsWare的注释链接到,它在viewHolder中实现了OnClickListener接口。

下面是ViewHolder的一个简单例子:

    TextView textView;//declare global with in adapter class


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 recycler view
if(getLayoutPosition()==0){
//Do whatever you want here


}else if(getLayoutPosition()==1){
//Do whatever you want here


}else if(getLayoutPosition()==2){


}else if(getLayoutPosition()==3){


}else if(getLayoutPosition()==4){


}else if(getLayoutPosition()==5){


}


//or you can use For loop if you have long list of items. Use its length or size of the list as
for(int i = 0; i<exampleList.size(); i++){


}




}
}

Adapter看起来像这样:

    @Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view =LayoutInflater.from(parent.getContext()).inflate(android.R.layout.simple_list_item_1, parent, false);


return new ViewHolder(view);
}

这就是我最后需要的东西,以防有人发现它有用:

public static class ViewHolder extends RecyclerView.ViewHolder {


public ViewHolder(View item) {


super(item);
item.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Log.d("RecyclerView", "onClick:" + getAdapterPosition());
}
});


}
}

来源:# EYZ0

下面是为RecyclerView实现OnClickListener的一种更好且不那么紧密耦合的方法。

用法片段:

RecyclerView recyclerView = findViewById(R.id.recycler);
recyclerView.addOnItemTouchListener(
new RecyclerItemClickListener(context, recyclerView ,new RecyclerItemClickListener.OnItemClickListener() {
@Override public void onItemClick(View view, int position) {
// do whatever
}


@Override public void onLongItemClick(View view, int position) {
// do whatever
}
})
);

# EYZ0实现:

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 {
private OnItemClickListener mListener;


public interface OnItemClickListener {
public void onItemClick(View view, int position);


public void onLongItemClick(View view, int position);
}


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 child = recyclerView.findChildViewUnder(e.getX(), e.getY());
if (child != null && mListener != null) {
mListener.onLongItemClick(child, recyclerView.getChildAdapterPosition(child));
}
}
});
}


@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 true;
}
return false;
}


@Override public void onTouchEvent(RecyclerView view, MotionEvent motionEvent) { }


@Override
public void onRequestDisallowInterceptTouchEvent (boolean disallowIntercept){}
}

对我来说,这是最好的方法:

class YourRecyclerAdapter extends RecyclerView.Adapter<ContactViewHolder> implements View.OnClickListener {
...
@Override
public void onClick(View view) {
int itemPosition = vRecycle.getChildPosition(view);
//And use itemPosition to get the item from your collection. This way you dont restrain the ViewHolder with a OnClick callback
}
...
}

到目前为止,所有的答案都是很好的解决方案,但是如果你不想处理太多的实现细节,只是想让它类似于ListView的工作方式,我建议使用twway - view,如下所示:

https://github.com/lucasr/twoway-view

请注意,这个实现还支持长按项目,以及支持按下状态(这是这个问题的其他解决方案所缺乏的重要内容)。

如果不想使用整个库,可以查看ClickItemTouchListener类,如果需要,可以将其作为独立的类使用。我发现它目前唯一的问题是长按+滚动,它似乎有不正确的行为。

这对我来说很管用。将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();
}
});
}

基于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) {
// ...
}
}));

以下是我所做的。这个解决方案同时支持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()也被调用(当点击图像)。

这是我的自定义适配器的完整代码,这段代码将用XML文件“list_item”中定义的列表项膨胀行,它还将在具有各自位置的所有列表项行上执行单击事件。

public class MyCustomAdapter extends RecyclerView.Adapter`<`AdapterMyCustomAdapter.ViewHolder> {


public static class ViewHolder extends RecyclerView.ViewHolder implements OnClickListener {
public onItemClickListener mListener;
public ViewHolder(View v, onItemClickListener listener) {
super(v);
mListener =listener;
v.setOnClickListener(this);
}


@Override
public void onClick(View v) {
mListener.onRecyclerItemClick(v, getPosition());
}


public static interface onItemClickListener {
public void onRecyclerItemClick(View view , int position);
}
}


@Override
public int getItemCount() {
return 5;
}


@Override
public void onBindViewHolder(ViewHolder holder, int pos) {


}


@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int position) {
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.list_item, parent, false);


/* here list_item is an xml file we want to inflate ...it is same as we do in case of listview for customization.*/


MyCustomAdapter.ViewHolder vh = new ViewHolder(v, new MyCustomAdapter.ViewHolder.onItemClickListener() {


@Override
public void onRecyclerItemClick(View view, int position) {
System.out.println("clicked on list item at position " +position);
}
});
return vh;
}
}

你可以实现OnClickListener到你的ViewHolder类

public static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
public Item item
@InjectView(R.id.tv_title)
public TextView tvTitle;
@InjectView(R.id.rl_row)
public RelativeLayout rlRow;


public ViewHolder(View v) {
super(v);
ButterKnife.inject(this, v);
v.setOnClickListener(this);
}


@Override
public void onClick(View view) {
Log.e("item title",item.getTitle());
}
}

onBindViewHolder设置视图持有者的项目

public void onBindViewHolder(ViewHolder holder, int position) {
holder.tvTitle.setText(objects.get(position).getTitle());
holder.item = objects.get(position);
}

如果你想捕捉单个项目上的点击事件,那么只需在ViewHolder类中实现OnClickListener,然后在单个视图或整个itemView上设置点击侦听器。

下面的例子说明了同样的情况

public  class ContactViewHolder extends RecyclerView.ViewHolder implements OnClickListener
{
TextView txt_title,txt_name,txt_email;


public ContactViewHolder(View itemView)
{
super(itemView);
txt_title = (TextView)itemView.findViewById(R.id.txt_title);
txt_name  = (TextView)itemView.findViewById(R.id.txt_name);
txt_email = (TextView)itemView.findViewById(R.id.txt_email);


txt_name.setOnClickListener(this);
txt_email.setOnClickListener(this);
itemView.setOnClickListener(this);
}


@Override
public void onClick(View v) {
// TODO Auto-generated method stub


if(v == itemView)
{
Toast.makeText(RecyclerDemoActivity.this, "Visiting Card Clicked is ==>"+txt_name.getText(), Toast.LENGTH_SHORT).show();
}


if(v == txt_name)
{
Toast.makeText(RecyclerDemoActivity.this, "Name ==>"+txt_name.getText(), Toast.LENGTH_SHORT).show();
}


if(v == txt_email)
{
Toast.makeText(RecyclerDemoActivity.this, "Email ==>"+txt_email.getText(), Toast.LENGTH_SHORT).show();
}
}


}
}

这对我来说很难在活动中有一个项目点击监听器,也有一个项目的单一视图的点击监听器,不会触发项目点击监听器。在玩了Jacob Tabak的回答后,我尊重他的回答,如果项目内没有其他触摸操作,就点击项目。

我有一个自定义的OnClickListener接口,其中有一个项目单击事件,它保存了被单击的项目的视图和来自适配器的项目位置。我在构造函数(或者它可以是setter)中呈现它的一个实例,并将它附加到视图持有者容器click listener。

我也有其他的点击监听器在适配器(可以在视图持有人),这将处理当前的视图点击从容器。

 public class MyRecyclerAdapter extends RecyclerView.Adapter<MyViewHolder> {


private ArrayList<String> mData;
private OnItemClickListener mOnItemClickListener;


public interface OnItemClickListener {
public void onItemClick(View view, int position);
}


public MyRecyclerAdapter(ArrayList<String> itemsData,
OnItemClickListener onItemClickListener) {
mOnItemClickListener = onItemClickListener;
this.mData = itemsData;
}


@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {


View layoutView = LayoutInflater.from(mContext).inflate(
R.layout.list_item, parent, false);


final MyViewHolder viewHolder = new MyViewHolder(layoutView);


viewHolder.container.setOnClickListener(new OnClickListener() {


@Override
public void onClick(View v) {
mOnItemClickListener.onItemClick(v, viewHolder.getAdapterPosition());
}
});


viewHоlder.button.setOnClickListener(new OnClickListener() {


@Override
public void onClick(View v) {
//do button click work here with
// mData.get( viewHolder.getAdapterPosition() );
}
});


return viewHolder;
}


@Override
public int getItemCount() {
return mData.size();
}}

在活动中,您需要通过传递OnItemClickListener的实例来初始化适配器

public class FeedActivity extends ActionBarActivity {


@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);


...


RecyclerView recyclerView = (RecyclerView) findViewById(R.id.my_recycler_view);


.....


MyRecyclerAdapter adapter = new MyRecyclerAdapter(new ArrayList<String>(), new OnItemClickListener() {


@Override
public void onItemClick(View view, int position) {


///list item was clicked
}
});


recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setAdapter(mFeedsAdapter);
}

还有我的ViewHolder

public class MyViewHolder extends RecyclerView.ViewHolder {


public Button button;
public View container;


public MyViewHolder(View itemLayoutView) {
super(itemLayoutView);


container = itemLayoutView;
button = (Button) itemLayoutView.findViewById(R.id.button);
}}

RecyclerView没有OnClickListener,我们必须自己实现它。

我喜欢在Adapter中添加一个OnItemClickListener接口,当您从ViewHolder中单击项目视图时调用onClick方法。因此,管理项目点击的职责不在ViewHolderAdapter范围内。将决定做什么的活动或片段

为监听器和监听器对象添加接口。

public class ItemsAdapter extends RecyclerView.Adapter<ItemsAdapter.ViewHolder> {


...


private static OnItemClickListener onItemClickListener;


...


public static interface OnItemClickListener {
public void onItemClick(View view, int position);
}


...
}

我们捕获项目根视图的单击,以及当回调被触发时适配器上的onClick侦听器调用。

public class ItemsAdapter extends RecyclerView.Adapter<ItemsAdapter.ViewHolder> {


...


private static OnItemClickListener onItemClickListener;


...


public static interface OnItemClickListener {
public void onItemClick(View view, int position);
}


...


public static class ViewHolder extends RecyclerView.ViewHolder {
public ImageView imageView;


public ViewHolder(View itemRootView) {
super(itemRootView);
imageView = (ImageView) itemRootView.findViewById(R.id.itemImage);


itemRootView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
int position  = ViewHolder.super.getAdapterPosition();
onItemClickListener.onItemClick(view,position);
}
});
}
}
}

由于活动或片段,片段在我们的情况下,我们分配一个监听器到适配器和onClick回调,我们将获得选定的项目的位置和打开一个详细的活动项目。

public class ItemsFragment extends Fragment {
...
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
...
((ItemsAdapter) adapter).setOnItemClickListener(new ItemsAdapter.OnItemClickListener() {
@Override
public void onItemClick(View view, int position) {
//Do something when an item has been clicked
}
});
...
}
...
}

你可以传递一个clickListenerAdapter

在你的Activity:

private View.OnClickListener mItemClick = new View.OnClickListener() {


@Override
public void onClick(View v) {
Intent intent = null;
int position = list.getChildPosition(v);
switch (position) {
case 0:
intent = new Intent(MainActivity.this, LeakCanaryActivity.class);
break;
case 1:
intent = new Intent(MainActivity.this, ButterKnifeFragmentActivity.class);
break;
}
if (intent != null) {
MainActivity.this.startActivity(intent);
}
}
};

然后传递给Adapter:

MainAdapter mainAdapter = new MainAdapter(this, mItemClick);

AdapteronCreateViewHolder中:

 @Override
public MainAdapter.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int position) {
View itemView = activity.getLayoutInflater().inflate(R.layout.main_adapter_item, viewGroup, false);
ViewHolder holder = new ViewHolder(itemView);
itemView.setOnClickListener(mItemClick);
return holder;
}

将类标记为抽象并实现OnClick方法

public abstract class MainGridAdapter extends
RecyclerView.Adapter<MainGridAdapter.ViewHolder> {
private List<MainListItem> mDataset;


// Provide a reference to the views for each data item
// Complex data items may need more than one view per item, and
// you provide access to all the views for a data item in a view holder
public class ViewHolder extends RecyclerView.ViewHolder {
// each data item is just a string in this case
public TextView txtHeader;
public TextView txtFooter;


public ViewHolder(View v) {
super(v);
txtHeader = (TextView) v.findViewById(R.id.firstLine);
txtFooter = (TextView) v.findViewById(R.id.secondLine);
}
}


public void add(int position, MainListItem item) {
mDataset.add(position, item);
notifyItemInserted(position);
}


public void remove(MainListItem item) {
int position = mDataset.indexOf(item);
mDataset.remove(position);
notifyItemRemoved(position);
}


// Provide a suitable constructor (depends on the kind of dataset)
public MainGridAdapter(List<MainListItem> myDataset) {
mDataset = myDataset;
}


// Create new views (invoked by the layout manager)
@Override
public MainGridAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
// create a new view
View v = LayoutInflater.from(parent.getContext()).inflate(
R.layout.list_item_grid_line, parent, false);
// set the view's size, margins, paddings and layout parameters
ViewHolder vh = new ViewHolder(v);
return vh;
}


// Replace the contents of a view (invoked by the layout manager)
@Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
// - get element from your dataset at this position
// - replace the contents of the view with that element
OnClickListener clickListener = new OnClickListener() {
@Override
public void onClick(View v) {
onItemClicked(position);
}
};
holder.itemView.setOnClickListener(clickListener);
holder.txtHeader.setOnClickListener(clickListener);
holder.txtFooter.setOnClickListener(clickListener);
final MainListItem item = mDataset.get(position);
holder.txtHeader.setText(item.getTitle());
if (TextUtils.isEmpty(item.getDescription())) {
holder.txtFooter.setVisibility(View.GONE);
} else {
holder.txtFooter.setVisibility(View.VISIBLE);
holder.txtFooter.setText(item.getDescription());
}
}


// Return the size of your dataset (invoked by the layout manager)
@Override
public int getItemCount() {
return mDataset.size();
}


public abstract void onItemClicked(int position);

在绑定事件中实现单击处理程序,使其只有一个事件实现

执行此:

mAdapter = new MainGridAdapter(listItems) {
@Override
public void onItemClicked(int position) {
showToast("Item Clicked: " + position, ToastPlus.STYLE_INFO);
}
};

同样可以做长时间点击

这是我的代码片段

v.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v)
{
int newposition = MainActivity.mRecyclerView.getChildAdapterPosition(v);
Intent cardViewIntent = new Intent(c, in.itechvalley.cardviewexample.MainActivityCards.class);
cardViewIntent.putExtra("Position", newposition);
c.startActivity(cardViewIntent);
}
});

v是从onCreateViewHolder变成视图

c = 上下文

下面是我做的阅读更多&下载要点

在这里添加相同的内容

CustomItemClickListener.java

public interface CustomItemClickListener {
public void onItemClick(View v, int position);
}

ItemsListAdapter.java

public class ItemsListAdapter extends RecyclerView.Adapter<ItemsListAdapter.ViewHolder> {
ArrayList<ItemListSingleItem> data;


Context mContext;
CustomItemClickListener listener;


@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View mView = LayoutInflater.from(parent.getContext()).inflate(R.layout.items_list_single_item, parent, false);
final ViewHolder mViewHolder = new ViewHolder(mView);
mView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
listener.onItemClick(v, mViewHolder.getAdapterPosition());
}
});
return mViewHolder;
}


@Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.itemTitle.setText(Html.fromHtml(data.get(position).getTitle()));
if (!TextUtils.isEmpty(data.get(position).getThumbnailURL())) {
// I Love picasso library :) http://square.github.io/picasso/
Picasso.with(mContext).load(data.get(position).getThumbnailURL()).error(R.drawable.ic_no_image).
placeholder(R.drawable.ic_no_image).
transform(new RoundedCornersTransformation(5, 0)).
into(holder.thumbnailImage);
} else {
holder.thumbnailImage.setImageResource(R.drawable.ic_no_image);
}
}




@Override
public int getItemCount() {
return data.size();
}


public ItemsListAdapter(Context mContext, ArrayList<ItemsListSingleItem> data, CustomItemClickListener listener) {
this.data = data;
this.mContext = mContext;
this.listener = listener;
}


public static class ViewHolder extends RecyclerView.ViewHolder {
public TextView itemTitle;
public ImageView thumbnailImage;


ViewHolder(View v) {
super(v);
itemTitle = (TextView) v
.findViewById(R.id.post_title);
thumbnailImage = (ImageView) v.findViewById(R.id.post_thumb_image);
}
}
}

我是这样做的,没有不必要的类、检测器等。适配器中的简单代码。特别是针对longClick的更好解决方案。

public class PasswordAdapter extends RecyclerView.Adapter<PasswordAdapter.ViewHolder> {
private static ClickListener clickListener;


public static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener {
TextView name;


public ViewHolder(View itemView) {
super(itemView);
itemView.setOnClickListener(this);
itemView.setOnLongClickListener(this);
name = (TextView) itemView.findViewById(R.id.card_name);
}


@Override
public void onClick(View v) {
clickListener.onItemClick(getAdapterPosition(), v);
}


@Override
public boolean onLongClick(View v) {
clickListener.onItemLongClick(getAdapterPosition(), v);
return false;
}
}


public void setOnItemClickListener(ClickListener clickListener) {
PasswordAdapter.clickListener = clickListener;
}


public interface ClickListener {
void onItemClick(int position, View v);
void onItemLongClick(int position, View v);
}
}

然后在片段或活动中,点击:

PasswordAdapter mAdapter = ...;


mAdapter.setOnItemClickListener(new PasswordAdapter.ClickListener() {
@Override
public void onItemClick(int position, View v) {
Log.d(TAG, "onItemClick position: " + position);
}


@Override
public void onItemLongClick(int position, View v) {
Log.d(TAG, "onItemLongClick pos = " + position);
}
});

从上面的大多数答案来看,他们似乎将onclicklistener设置为单个项目。然而,我要提供的解决方案很简单,但对许多人来说并不直观。许多人忘记了其他组件总是在父组件中,用于在List或Recycler视图中显示项目。这个解决方案只是为这个父视图设置一个onclick监听器,然后播放回合。该解决方案还包括一种从列表或回收视图传递被单击的项目位置的方法。这里,我们的主根视图是一个来自android支持库的CardView。下面是示例代码

public class ListAdapter extends RecyclerView.Adapter<ListAdapter.ViewHolder> {


public static final String LOG_TAG = ListAdapter.class.getSimpleName();
private Cursor mDataset;
private Context mContext;
private ViewHolder mViewHolder;


// Provide a suitable constructor (depends on the kind of dataset)
public ListAdapter(Context context, Cursor Dataset) {
mDataset = Dataset;
mContext = context;
}


// Create new views (invoked by the layout manager)
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {


// create a new view
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.list_business_view, parent, false);


mViewHolder = new ViewHolder(v);
return mViewHolder;
}


public void setData(Cursor newdata) {
this.mDataset = newdata;
}


// Replace the contents of a view (invoked by the layout manager)
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
//Bind data to other items here. To save time, i have ommited that.
//here is where we attach a click listerner for an item in the recycler list rather than for each element of a given item.
holder.card.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(mContext, " Just cliked item at position " + itemPosition, Toast.LENGTH_LONG).show();


}
});


}
}


// Return the size of your dataset (invoked by the layout manager)
@Override
public int getItemCount() {
if (null != mDataset) {
return mDataset.getCount();
}
return 0;


}




// Provide a reference to the views for each data item
// Complex data items may need more than one view per item, and
// you provide access to all the views for a data item in a view holder
public static class ViewHolder extends RecyclerView.ViewHolder{
// each data item is just a string in this case
public final TextView mBusinesssName; // View for the business name
public final TextView mBusinessCategory; //View for the category name
public final ImageView businessImage; // View for the business category image Image
public final TextView mBusinessDistance; // View for the distance
public final CardView card;


public ViewHolder(View view) {
super(view);
mBusinesssName = (TextView) view.findViewById(R.id.list_item_name_textview);
mBusinessCategory = (TextView) view.findViewById(R.id.list_item_category_textview);
mBusinessDistance = (TextView) view.findViewById(R.id.list_item_dist_textview);
businessImage = (ImageView) view.findViewById(R.id.list_item_icon);
card = (CardView) view.findViewById(R.id.card_view);


}
}
}

这里有一个策略,其结果类似于ListView实现,因为您可以在ActivityFragment级别而不是AdapterViewHolder级别中定义侦听器。它还定义了一些抽象类,这些抽象类负责适配器和持有者的大量样板工作。

抽象类

首先,定义一个抽象的Holder,它扩展了RecyclerView.ViewHolder,并定义了一个泛型数据类型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);
}

另外,创建一个抽象的Adapter,它扩展了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);
}
}

最后,在包含RecyclerViewActivityFragment类中,你会有这样的代码:

// 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;
}
};
不幸的是,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);
}
}

你还需要使用ids.xml定义R.id.item_click_support:

 <?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

很简单,添加这个类:

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();
}
}
我们可以使用Java弱引用来做到这一点。 从语义上讲,视图持有者应该响应click事件或将其委托给正确的响应器

我们的目标:

  1. Viewholder应该对响应事件的类一无所知,除非它实现了某个接口。
  2. 点击处理程序应该得到被点击的视图在RecyclerView中的位置。
  3. 我们应该能够辨别出在视图持有人中点击了哪一个视图。
  4. 保持所有组件之间的松散耦合,不要造成任何保留周期。

步骤:

  1. 创建一个接口来处理单击响应。

  2. 在处理单击的Activity中实现此接口。

  3. 在RecyclerView适配器中添加一个成员变量来保存弱引用和设置弱引用的构造函数。

  4. 在RecyclerView ViewHolder中执行同样的操作,并添加一个成员变量来跟踪位置。

  5. 在ViewHolder中为你想要的任何视图设置on click监听器,然后回调到responder来处理它们。

  6. 更改onBindViewHolder方法来设置绑定时的位置。

  7. 将响应器传递给ViewHolder。

  8. 在响应器中,您现在可以在视图上使用getId()来确定单击了哪个视图。

这里是一个要点,这样你就可以看到它是如何组合在一起的: # EYZ0 < / p >

太简单和有效了。

而不是在视图holder中实现接口View.OnClickListener或在activity中创建和实现接口 我使用这段代码简单的在OnClickListener上实现

public static class SimpleStringRecyclerViewAdapter
extends RecyclerView.Adapter<SimpleStringRecyclerViewAdapter.ViewHolder> {


// Your initializations goes here...
private List<String> mValues;


public static class ViewHolder extends RecyclerView.ViewHolder {


//create a variable mView
public final View mView;


/*All your row widgets goes here
public final ImageView mImageView;
public final TextView mTextView;*/


public ViewHolder(View view) {
super(view);
//Initialize it here
mView = view;


/* your row widgets initializations goes here
mImageView = (ImageView) view.findViewById(R.id.avatar);
mTextView = (TextView) view.findViewById(android.R.id.text1);*/
}
}


public String getValueAt(int position) {
return mValues.get(position);
}


public SimpleStringRecyclerViewAdapter(Context context, List<String> items) {


mBackground = mTypedValue.resourceId;
mValues = items;
}


@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.list_item, parent, false);
view.setBackgroundResource(mBackground);
return new ViewHolder(view);
}


@Override
public void onBindViewHolder(final ViewHolder holder, int position) {
holder.mBoundString = mValues.get(position);
holder.mTextView.setText(mValues.get(position));


//Here it is simply write onItemClick listener here
holder.mView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Context context = v.getContext();
Intent intent = new Intent(context, ExampleActivity.class);


context.startActivity(intent);
}
});
}


@Override
public int getItemCount() {
return mValues.size();
}
}

我有很好的解决方案RecyclerViewonItemClickListener的项目和子项

创建接口

public interface OnRecyclerViewItemClickListener
{
/**
* Called when any item with in recyclerview or any item with in item
* clicked
*
* @param position
*            The position of the item
* @param id
*            The id of the view which is clicked with in the item or
*            -1 if the item itself clicked
*/
public void onRecyclerViewItemClicked(int position, int id);
}

然后按以下方式在适配器的onBindViewHolder方法中使用它

/**
* Custom created method for Setting the item click listener for the items and items with in items
* @param listener OnRecyclerViewItemClickListener
*/
public void setOnItemClickListener(OnRecyclerViewItemClickListener listener)
{
this.listener = listener;
}


@Override
public void onBindViewHolder(ViewHolder viewHolder, final int position)
{
    

// viewHolder.albumBg.setBackgroundResource(_itemData[position]
// .getImageUrl());
    

viewHolder.albumName.setText(arrayList.get(position).getName());
viewHolder.artistName.setText(arrayList.get(position).getArtistName());
String imgUrl = arrayList.get(position).getThumbImageUrl();
    

makeImageRequest(imgUrl, viewHolder);
viewHolder.parentView.setOnClickListener(new View.OnClickListener()
{
    

@Override
public void onClick(View v)
{
listener.onRecyclerViewItemClicked(position, -1);
}
});
viewHolder.settingButton.setOnClickListener(new View.OnClickListener()
{
    

@Override
public void onClick(View v)
{
listener.onRecyclerViewItemClicked(position, v.getId());
}
});
    

}
    

// class to hold a reference to each item of RecyclerView
public static class ViewHolder extends RecyclerView.ViewHolder
{
    

public TextView albumName, artistName;
public ImageView albumIcon, settingButton;
public LinearLayout parentView;
    

public ViewHolder(View itemLayoutView)
{
super(itemLayoutView);
// albumBg = (LinearLayout) itemLayoutView
// .findViewById(R.id.albumDlbg);
albumName = (TextView) itemLayoutView.findViewById(R.id.albumName);
artistName = (TextView) itemLayoutView
.findViewById(R.id.artistName);
albumIcon = (ImageView) itemLayoutView.findViewById(R.id.albumIcon);
parentView = (LinearLayout) itemLayoutView
.findViewById(R.id.albumDlbg);
settingButton = (ImageView) itemLayoutView
.findViewById(R.id.settingBtn);
}
    

}

步骤3 -在你使用的活动或片段中找到并设置回收器视图

recyclerView = (RecyclerView) rootview.findViewById(R.id.vmtopsongs);


lm = new LinearLayoutManager(mActivity);
lm.setOrientation(LinearLayoutManager.VERTICAL);
recyclerView.setLayoutManager(lm);
recyclerView.addItemDecoration(
new HorizontalDividerItemDecoration.Builder(getActivity())
.paint(Utils.getPaint()).build());
PopularSongsadapter mAdapter = new PopularSongsadapter(gallery,
mActivity, true);
// set adapter
recyclerView.setAdapter(mAdapter);
mAdapter.setOnItemClickListener(this);
// set item animator to DefaultAnimator
recyclerView.setItemAnimator(new DefaultItemAnimator());

最后在使用recyclerview的activity或fragment中实现接口

@Override
public void onRecyclerViewItemClicked(int position, int id)
{
if(id==-1){
Toast.makeText(mActivity, "complete item clicked", Toast.LENGTH_LONG).show();
}else{
Toast.makeText(mActivity, "setting button clicked", Toast.LENGTH_LONG).show();
}
}

更新Kotlin语言 我已经更新了kotlin的代码,其中只有整个视图有点击监听器。你可以根据上面的java代码编辑界面和代码来设置子项点击监听器

适配器

class RecentPostsAdapter(private val list: MutableList<Post>) :
RecyclerView.Adapter<RecentPostsAdapter.ViewHolder>() {
private lateinit var onItemClickListener: OnItemClickListener


override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
return ViewHolder(
LayoutInflater.from(parent.context)
.inflate(R.layout.listitem_recent_post, parent, false)
)
}


override fun getItemCount(): Int {
return list.size
}


fun setOnItemClickListener(onItemClickListener: OnItemClickListener) {
this.onItemClickListener = onItemClickListener
}


private fun getItem(position: Int): Post {
return list[position]
}


override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.bind(getItem(position))
holder.itemView.setOnClickListener(View.OnClickListener {
onItemClickListener.onItemClick(
position
)
})
}


class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
private var imageView: NetworkImageView? = null
private var tvTitle: TextView? = null
private var tvExcerpt: TextView? = null
private var htmlSpanner: HtmlSpanner = HtmlSpanner()


init {
imageView = itemView.findViewById(R.id.niv_post_image)
tvTitle = itemView.findViewById(R.id.tv_post_title)
tvExcerpt = itemView.findViewById(R.id.tv_post_excerpt)
}


fun bind(post: Post) {
tvTitle?.text = post.title
tvExcerpt?.text = htmlSpanner.fromHtml(post.excerpt)
}
}


interface OnItemClickListener {
fun onItemClick(position: Int)
}
}

活动或片段

recyclerView = view.findViewById(R.id.rvHomeRecentPosts)
recyclerView.layoutManager = LinearLayoutManager(view.context)
list = mutableListOf()
recentPostsAdapter = RecentPostsAdapter(list)
recyclerView.adapter = recentPostsAdapter
recentPostsAdapter.setOnItemClickListener(object:RecentPostsAdapter.OnItemClickListener{
override fun onItemClick(position: Int) {
(activity as MainActivity).findNavController(R.id.nav_host_fragment).navigate(R.id.action_nav_home_to_nav_post_detail)
}


})

对我来说,最干净的方法就是这个。

适配器的构造函数

private class EnvironmentTypeRecyclerViewAdapter extends RecyclerView.Adapter<EnvironmentTypeRecyclerViewAdapter.ViewHolder>
{
private final EnvironmentTypeRecyclerViewAdapterListener mEnvironmentTypeRecyclerViewAdapterListener;
private List<Environment> mEnvironmentsData;


public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener
{
public ViewHolder(View v)
{
super(v);
v.setOnClickListener(this);


}


@Override
public void onClick(View v)
{
Environment environment = mEnvironmentsData.get(getAdapterPosition());
if (mEnvironmentTypeRecyclerViewAdapterListener != null && environment != null) {
mEnvironmentTypeRecyclerViewAdapterListener.onListItemSelected(environment);
}
}


public EnvironmentTypeRecyclerViewAdapter(List<SmallCellEnvironment> environments, EnvironmentTypeRecyclerViewAdapterListener environmentTypeRecyclerViewAdapterListener)
{
mEnvironmentTypeRecyclerViewAdapterListener = environmentTypeRecyclerViewAdapterListener;
mEnvironmentsData = environments;
}
}

链接接口

private interface EnvironmentTypeRecyclerViewAdapterListener
{
void onListItemSelected(Environment environment);
}

通常在CardView中有多个元素,因此需要一个布局视图来包装和组织它们。你可以添加一个OnClickListener到该布局视图。< br > 1。添加一个id到你的布局。在本例中是LinearLayout

<android.support.v7.widget.CardView
.....>


<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/card_view_linearLayout">


<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="name"
android:id="@+id/card_view_name" />


...


</LinearLayout>


</android.support.v7.widget.CardView>

# EYZ0 2。在内部的ViewHolder类中获取布局视图。

public static class ViewHolder extends RecyclerView.ViewHolder{
private TextView nameView;
...
private LinearLayout linearLayout;
public ViewHolder(View itemView) {
super(itemView);
nameView = (TextView)itemView.findViewById(R.id.card_view_name);
...
linearLayout = (LinearLayout)itemView.findViewById(R.id.card_view_linearLayout);
}
}

# EYZ0 3。将监听器添加到onBindViewHolder的布局中,并使用回调将数据发送到ActivityFragment(未测试)。

@Override
public void onBindViewHolder(TrackAdapter.ViewHolder holder, final int position) {
String str = mStringList.get(position);


holder.nameView.setText(str);
...
holder.linearLayout.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
callback.itemCallback(mStringList.get(position));
}
});
}

如何使用回调是另一个故事

我知道有很多答案,但我想我也可以提供我的实现。(详细信息可以在我回答了另一个问题上找到)。

因此,要添加单击侦听器,内部的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());
}
}
}

你需要添加的唯一其他东西是一个自定义接口的Adapter和一个setter方法:

private OnEntryClickListener mOnEntryClickListener;


public interface OnEntryClickListener {
void onEntryClick(View view, int position);
}


public void setOnEntryClickListener(OnEntryClickListener onEntryClickListener) {
mOnEntryClickListener = onEntryClickListener;
}

这样,新的、支持单击的Adapter就完成了。

现在,让我们用它…

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

这基本上是设置普通Adapter的方法,除了使用您创建的setter方法来控制当用户单击特定列表项时要做什么。

你也可以看看我在GitHub上做的一组关于Gist的例子:

# EYZ0

有更简单的方法。只需在根视图的onBindViewHolder中单击应用。

考虑这是你对适配器的看法,

<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:id="@+id/linearlayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">


<TextView
android:id="@+id/textview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="1dp"
android:textSize="15sp" />
</LinearLayout>

然后在适配器中执行以下操作

//get the layout and make view holder
@Override
public RVAdapter.ViewHolder1 onCreateViewHolder(ViewGroup parent, int viewType) {


View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.adapter_layout, null);
ViewHolder1 viewHolder = new ViewHolder1(view);
return viewHolder;
}


@Override
public void onBindViewHolder(RVAdapter.ViewHolder1 holder, int position) {


//apply on click on your root view
holder.linearlayout.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//Do on click stuff
}
});
}


//make references to views in layout including root view
public class ViewHolder1 extends RecyclerView.ViewHolder {


protected LinearLayout linearlayout = null
protected TextView textview = null;


public CareerLinksViewHolder(View itemView) {
super(itemView);


this.linearlayout = (LinearLayout) itemView.findViewById(R.id.linearlayout);
this.tvCompName = (TextView) itemView.findViewById(R.id.textview);
}
}

我已经为android开发了一个轻量级库,你可以访问https://github.com/ChathuraHettiarachchi/RecycleClick

并跟随下面的例子

RecycleClick.addTo(YOUR_RECYCLEVIEW).setOnItemClickListener(new RecycleClick.OnItemClickListener() {
@Override
public void onItemClicked(RecyclerView recyclerView, int position, View v) {
// YOUR CODE
}
});

你可以很容易地在ViewHolder类中定义setOnClickListener,如下所示:

public class ViewHolder extends RecyclerView.ViewHolder {
TextView product_name;


ViewHolder(View itemView) {
super(itemView);
product_name = (TextView) itemView.findViewById(R.id.product_name);
itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
int itemPosition = getLayoutPosition();
Toast.makeText(getApplicationContext(), itemPosition + ":" + String.valueOf(product_name.getText()), Toast.LENGTH_SHORT).show();
}
});
}
}

步骤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/

在Kotlin中也是如此

inner class MyViewHolder(v: View, myOnClickListener: MyOnClickListener) : RecyclerView.ViewHolder(v) {
init {
v.setOnClickListener { v -> myOnClickListener.onClick(v, adapterPosition) }
}
}


override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): MyViewHolder {
val view = LayoutInflater.from(viewGroup.context).inflate(R.layout.myview, viewGroup, false)
return MyViewHolder(view, mOnClickListener)
}


inner class MyOnClickListener {
fun onClick(view: View, position: Int) {
val item = mList[position]
Toast.makeText(view.context, item, Toast.LENGTH_LONG).show()
}
}

试试这个,很简单。这对我很管用。顺便说一句,我发现setOnClickListener在回收视图中不生效。

    recycler.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_UP) {
// anything todo
}
return true;
}
});

这是我重用OnClickListener的方法

  public class TestAdapter extends RecyclerView.Adapter<TestAdapter.MyviewHolder>
implements View.OnClickListener

取itemlayout的父项

  public class MyviewHolder extends RecyclerView.ViewHolder {


LinearLayout linearLayout_item;


public MyviewHolder(View itemView) {
super(itemView);
linearLayout_item=itemView.findViewById(R.id.linearLayout_item);
}
}

在onBindViewHolder中设置标签为位置

   @Override
public void onBindViewHolder(MyviewHolder holder, int position) {


holder.linearLayout_item.setTag(position);
holder.linearLayout_item.setOnClickListener(this);
}

在Onclick中

 @Override
public void onClick(View v) {


int position = (int) v.getTag();
switch (v.getId()) {
case R.id.linearLayout_item:


// do some thing with position


break;
}
}

nhaarman的 回答的Kotlin实现:

mRecyclerView.addOnItemTouchListener(object  : RecyclerItemClickListener(this, mRecyclerView,object :RecyclerItemClickListener.OnItemClickListener{
override fun onItemClick(view: View, position: Int) {


}


override fun onLongItemClick(view: View?, position: Int) {


}
}){})

RecyclerItemClickListener.java:

import android.content.Context
import android.support.v7.widget.RecyclerView
import android.view.GestureDetector
import android.view.MotionEvent
import android.view.View




open class RecyclerItemClickListener(context: Context, recyclerView: RecyclerView, private val mListener: OnItemClickListener?) : RecyclerView.OnItemTouchListener {


private var mGestureDetector: GestureDetector


interface OnItemClickListener {
fun onItemClick(view: View, position: Int)


fun onLongItemClick(view: View?, position: Int)
}


init {
mGestureDetector = GestureDetector(context, object : GestureDetector.SimpleOnGestureListener() {
override fun onSingleTapUp(e: MotionEvent): Boolean {
return true
}


override fun onLongPress(e: MotionEvent) {
val child = recyclerView.findChildViewUnder(e.x, e.y)
if (child != null && mListener != null) {
mListener.onLongItemClick(child, recyclerView.getChildAdapterPosition(child))
}
}
})
}


override fun onInterceptTouchEvent(view: RecyclerView, e: MotionEvent): Boolean {
val childView = view.findChildViewUnder(e.x, e.y)
if (childView != null && mListener != null && mGestureDetector.onTouchEvent(e)) {
mListener.onItemClick(childView, view.getChildAdapterPosition(childView))
return true
}
return false
}


override fun onTouchEvent(view: RecyclerView, motionEvent: MotionEvent) {}


override fun onRequestDisallowInterceptTouchEvent(disallowIntercept: Boolean) {}
}
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();
}
});
}
}

我已经看了所有的答案,并不是很满意。我找到了更简单快捷的方法。想分享给未来的读者。

  1. 选择任何View在你的单一回收项目。
  2. 获得这个View的父对象(确保你的施法适合ViewGroup)
  3. onClickListener设置为这个父节点。

示例代码(它写在你的adapteronBindViewHolder方法中):

@Override
public void onBindViewHolder(@NonNull final ViewHolder holder, final int position) {


ConstraintLayout parent = (ConstraintLayout) holder.title.getParent();
parent.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(context, "Clicked recycler view item at position " + position, Toast.LENGTH_SHORT).show();
}
});
}

在kotlin中使用构造函数实现

初始化Recyclerview构造函数,如下所示

class ListAdapter(
c: Context,
private var list: List<Project>,
private val itemClick: (Project) -> Unit
) : RecyclerView.Adapter<ListAdapter.ViewHolder>()

在onCreateViewHolder中返回itemClick

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int):ProjectViewHolder {
val view = inflater.inflate(R.layout.list_item, parent, false)
return ViewHolder(view, itemClick)
}

你onBindViewHolder

override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.bindProject(list[position])
}

然后用viewHolder类创建bindProject函数。

class ViewHolder(
view: View,
private val itemClick: (Project) -> Unit
) : RecyclerView.ViewHolder(view) {


private val clientTextCount = 7


val titleTextView: TextView = view.projectTitleTextView


fun bindProject(project: Project) {
with(project) {
titleTextView.text = name
itemView.setOnClickListener { itemClick(this) }
}
}
}

最后在您的活动中用lazy初始化适配器

private val adapter: ListAdapter by lazy {
ListAdapter(this, projectList, {
// Here you can implement your onClick function.
})
}

在适配器中为recyclerview添加新的列表初始化下面的方法

fun setProjects(projects: List<Project>) {
projectList = projects
notifyDataSetChanged()
}

并在活动中的任何地方调用setProjects方法。

adapter.setProjects(projects)

就是这样。

这里有一个简单明了的方法,就是在你的ReacyclerView ViewHolder中添加

public static class MyViewholder extends RecyclerView.ViewHolder {


public MyViewholder(View itemView) {
super(itemView);


itemView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Log.d("Tag", "onClick:" + getAdapterPosition());
}
});


}
}

getAdapterPosition()返回当前被点击的项目位置

对于kotlin处理点击recyclerviewanser基于雅各布斯anser

kotlin RecyclerViewClick #RecyclerViewClick # kotlin

1)创建类RecyclerItemClickListener

class RecyclerItemClickListener(context: Context, recyclerView: RecyclerView, listner: OnItemClickListener) : RecyclerView.OnItemTouchListener {
var mGestureDetector: GestureDetector
var mListner: OnItemClickListener
interface OnItemClickListener {
fun onItemClick(view: View, position: Int)
fun onLongItemClick(view: View, position: Int)
}
init {
this.mListner = listner
mGestureDetector = GestureDetector(context, object : GestureDetector.SimpleOnGestureListener() {
override fun onSingleTapUp(e: MotionEvent?): Boolean {
return true
}
override fun onLongPress(e: MotionEvent?) {
val child: View? = recyclerView.findChildViewUnder(e!!.getX(), e.getY())
if (child != null && mListner != null) {
mListner.onLongItemClick(child, recyclerView.getChildAdapterPosition(child))
}


}


})
}
override fun onTouchEvent(rv: RecyclerView, e: MotionEvent) {
}


override fun onInterceptTouchEvent(view: RecyclerView, e: MotionEvent): Boolean {
val childView: View? = view.findChildViewUnder(e!!.getX(), e.getY())
if (childView != null && mListner != null && mGestureDetector.onTouchEvent(e)) {
mListner.onItemClick(childView, view.getChildAdapterPosition(childView))
return true
}
return false
}


override fun onRequestDisallowInterceptTouchEvent(disallowIntercept: Boolean) {
}


}

2)点击任意回收视图(activity/fragment)

 recyclerView.addOnItemTouchListener(
RecyclerItemClickListener(
this, recyclerView, object : RecyclerItemClickListener.OnItemClickListener {
override fun onItemClick(view: View, position: Int) {


}


override fun onLongItemClick(view: View, position: Int) {
}
})
)

让我们看看如何在Jetpack / AndroidX中实现这一点

你需要像这样在视图模型类中创建一个可观察对象

private MutableLiveData<Integer> adapterItem = new MutableLiveData<>();


public MutableLiveData<Integer> getAdapterItem() {
return adapterItem;
}


public void setAdapterItem(int adapterItem) {
this.getAdapterItem().setValue(adapterItem);
}

然后在适配器类中,确保将viewmodel引用作为构造函数的参数传递,然后在vieholder上实现clicklistener

    public MyViewHolder(@NonNull View itemView) {
super(itemView);
if(itemView != null){
itemView.setOnClickListener(v -> {
int adapterPosition = getAdapterPosition();
viewModel.setAdapterItem(adapterPosition);
});


};
}

然后在活动类中观察这些变化

    viewModel.getAdapterItem().observe(this, position -> {
Log.w(TAG, "clicked: " + ridesArray.get(position));
});

我的方式

活动课上:

    public class MyActivity extends AppCompatActivity implements EmployeeAdapter.ClickListener {
...
@Override
public void onClick(int position) { ... }
...
}

适配器类:

    public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {
...
@Override
public void onBindViewHolder(){
holder.textView1.setOnClickListener(v -> clickListener.onClick(position));
}
...
public interface ClickListener {
void onClick(int position);
}
...
}

recyclerview with click listener

在适配器类中添加接口。

public interface SelectedUser{


void selectedUser(UserModel userModel);


}

在mainactivity中实现你的接口并覆盖selectedUser方法。

@Override
public void selectedUser(UserModel userModel) {


startActivity(new Intent(MainActivity.this, SelectedUserActivity.class).putExtra("data",userModel));


}

完整的教程在这里检查加上源代码。 # EYZ0 < / p >

这个作品。

public class ServiceListAdapter extends RecyclerView.Adapter<ServiceListAdapter.ViewHolder> {


private final Context mContext;
private List<ServiceListModel> categoryList;
private View.OnClickListener onClickListener;


public ServiceListAdapter(Context mContext, List<ServiceListModel> categoryList, View.OnClickListener onClickListener) {
this.categoryList = categoryList;
this.mContext = mContext;
this.onClickListener = onClickListener;
}


@Override
public ViewHolder onCreateViewHolder(final ViewGroup parent, final int viewType) {
final LayoutInflater inflater = LayoutInflater.from(parent.getContext());
final RowServiceListBinding binding = DataBindingUtil.inflate(inflater, R.layout.row_service_list, parent, false);
return new ViewHolder(binding.getRoot(), binding);
}


@Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
holder.binding.rlService.setOnClickListener(onClickListener);
holder.binding.rlService.setTag(position);
}


@Override
public int getItemCount() {
return categoryList.size();
}


public class ViewHolder extends RecyclerView.ViewHolder {
private final RowServiceListBinding binding;


public ViewHolder(final View view, final RowServiceListBinding binding) {
super(view);
this.binding = binding;
}


@UiThread
public void bind(final ServiceListModel mAddressModel) {
//this.binding.setAddress(mAddressModel);
}
}
}

在活动/片段中使用

ServiceListAdapter adapter = new ServiceListAdapter(context, serviceList, new View.OnClickListener() {
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.rlService:
int pos = (int) v.getTag();
serviceList.remove(position);
break;
}
}
});

别白费力气了!这个特定用例的代码包含在Android Studio附带的主/详细流程启动项目中。

从Android Studio选择:

  1. # EYZ0比;# EYZ1比;# EYZ2。
  2. 手机和平板电脑选项卡中选择< >强主/明细流< / >强,如下所示。

enter image description here

  1. 用Kotlin或Java创建项目。
  2. 利润。

我不会在这里包括谷歌的ootb演示项目的代码,但我会概述谷歌提供的示例中的主要设计方法:

  • 项目OnClickListener被创建为只有一次,并被分配给您的RecyclerView.Adapter实现中的一个字段。
  • onBindViewHolder()中,你应该设置相同,预先创建 onClickListener对象在你的ViewHolder实例上使用holder.itemView.setOnClickListener(mOnClickListener) (避免在每个方法调用上都创建一个新实例!);如果你需要在ViewHolder中捕获一些特定元素的点击,那么扩展ViewHolder并将你需要的元素作为字段公开,这样你就可以在onBindViewHolder()中附加任何你需要的侦听器-再次强调,不要在每个方法调用上重新创建侦听器-将它们初始化为实例字段并根据需要附加它们。
  • 你可以使用.setTag()来传递状态给你的viewHolder,例如在演示中使用的holder.itemView.setTag(mValues.get(position));

根据Yigit Boyar,在RecyclerView上注册单击的最好方法是在viewholder的创建中定义单击,而不是为onBindViewHolder绑定的每个项创建一个新的onClickListener

例子

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseViewHolder<*> {
val itemBinding = LayoutInflater.from(context).inflate(R.layout.my_layout, parent, false)
val vh = MainViewHolder(itemBinding)


vh.itemView.setOnClickListener {
val pos = vh.adapterPosition
if(pos != NO_POSITION){
itemClickLister.onCocktailClick(myList[pos],pos)
}
}
return vh
}