I want to set up an onClickListener within my RecyclerView adapter so I can easily refer to the other views to retrieve their tags.
Is it possible to set up an onClickListener in a RecyclerView adapter? How would I do it? Would it affect performance?
Here is my RecyclerView adapter:
public class PostRecyclerAdapter extends RecyclerView.Adapter<PostRecyclerAdapter.ViewHolder> {
private Context context;
private List<Post> mDataset;
public static class ViewHolder extends RecyclerView.ViewHolder implements View.OnCreateContextMenuListener {
public LinearLayout mainLayout;
public TextView username;
public ImageView image;
public ViewHolder(LinearLayout view) {
super(view);
view.setOnCreateContextMenuListener(this);
mainLayout = (LinearLayout) view.findViewById(R.id.main_view);
username = (TextView) view.findViewById(R.id.username);
image = (ImageView) view.findViewById(R.id.image);
}
}
public PostRecyclerAdapter(Context context, List<Post> myDataset) {
this.context = context;
this.mDataset = myDataset;
}
@Override
public PostRecyclerAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.post_layout, parent, false);
ViewHolder vh = new ViewHolder((LinearLayout) view);
return vh;
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
Post postItem = mDataset.get(position);
holder.username.setText(postItem.getUserame());
}
@Override
public int getItemCount() {
return mDataset.size();
}
}
I would like to suggest a much simpler approach than the one given above.
in your adapter you would have written static view holder class right for that add the following code
public static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
// your views declared here
CardView cardView;
public ViewHolder(View itemView) {
super(itemView);
// your view initialised here
cardView=itemView.findViewById(R.id.card_view);
cardView.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.card_view:
// your logic
break;
}
}
}
by doing so you can handle individual click of your layout as well as the entire layout click
You can use GestureDetector for this. This is very simple to use :
Create A class RecyclerTouchListener :
public class RecyclerTouchListener implements RecyclerView.OnItemTouchListener {
private GestureDetector gestureDetector;
private ClickListener clickListener;
public RecyclerTouchListener(Context context, final RecyclerView recyclerView, final ClickListener 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.getChildAdapterPosition(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) {
}
public interface ClickListener {
void onClick(View view, int position);
void onLongClick(View view, int position);
}
}
and you can use this class as follow :
rvFilterOptions = (RecyclerView) rootView.findViewById(R.id.rvCommon);
rvFilterOptions.setHasFixedSize(true);
rvFilterOptions.addItemDecoration(new DividerItemDecoration(getActivity(),
DividerItemDecoration.VERTICAL_LIST));
LinearLayoutManager mLayoutManager = new LinearLayoutManager(getActivity());
rvFilterOptions.setLayoutManager(mLayoutManager);
rvFilterOptions.addOnItemTouchListener(new RecyclerTouchListener(getActivity(), rvFilterOptions, new RecyclerTouchListener.ClickListener() {
@Override
public void onClick(View view, int position) {
// Perform click operation and you can get post item from array using position
}
@Override
public void onLongClick(View view, int position) {
// Perform Long click operation
}
}));
Note : Concept is taken from LINK
This is simplest implementation but this will be inside recyclerviews adapter. If you want to get row item clicklistener in activity then use Interface.
public class PostRecyclerAdapter extends RecyclerView.Adapter<PostRecyclerAdapter.ViewHolder> {
private Context context;
private List<Post> mDataset;
public static class ViewHolder extends RecyclerView.ViewHolder implements View.OnCreateContextMenuListener {
public LinearLayout mainLayout;
public TextView username;
public ImageView image;
public View mRowItem;
public ViewHolder(LinearLayout view) {
super(view);
view.setOnCreateContextMenuListener(this);
mRowItem = view;
mainLayout = (LinearLayout) view.findViewById(R.id.main_view);
username = (TextView) view.findViewById(R.id.username);
image = (ImageView) view.findViewById(R.id.image);
}
}
public PostRecyclerAdapter(Context context, List<Post> myDataset) {
this.context = context;
this.mDataset = myDataset;
}
@Override
public PostRecyclerAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.post_layout, parent, false);
ViewHolder vh = new ViewHolder((LinearLayout) view);
return vh;
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
Post postItem = mDataset.get(position);
holder.username.setText(postItem.getUserame());
//Whole row item
holder.mRowItem.setTag(position);
holder.mRowItem.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int pos = (int) v.getTag();
// handle your row item click.
}
});
}
@Override
public int getItemCount() {
return mDataset.size();
}
}