I am experimenting with the support library\'s recyclerview and cards. I have a recyclerview of cards. Each card has an \'x\' icon at the top right corner to remove it:
No need to have your ViewHolder implementing View.OnClickListener. You can get directly the clicked position by setting a click listener in the method onCreateViewHolder of RecyclerView.Adapter here is a sample of code :
public class ItemListAdapterRecycler extends RecyclerView.Adapter<ItemViewHolder>
{
private final List<Item> items;
public ItemListAdapterRecycler(List<Item> items)
{
this.items = items;
}
@Override
public ItemViewHolder onCreateViewHolder(final ViewGroup parent, int viewType)
{
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_row, parent, false);
view.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View view)
{
int currentPosition = getClickedPosition(view);
Log.d("DEBUG", "" + currentPosition);
}
});
return new ItemViewHolder(view);
}
@Override
public void onBindViewHolder(ItemViewHolder itemViewHolder, int position)
{
...
}
@Override
public int getItemCount()
{
return items.size();
}
private int getClickedPosition(View clickedView)
{
RecyclerView recyclerView = (RecyclerView) clickedView.getParent();
ItemViewHolder currentViewHolder = (ItemViewHolder) recyclerView.getChildViewHolder(clickedView);
return currentViewHolder.getAdapterPosition();
}
}
Personally, the simplest way that I have found and works great for me is as follows:
Create an interface inside your "RecycleAdapter" Class (Subclass)
public interface ClickCallback {
void onItemClick(int position);
}
Add a variable of the interface as a parameter in the Constructor.
private String[] items;
private ClickCallback callback;
public RecyclerAdapter(String[] items, ClickCallback clickCallback) {
this.items = items;
this.callback = clickCallback;
}
Set a Click listener in the ViewHolder (another subclass) and pass the 'position' to through the interface
AwesomeViewHolder(View itemView) {
super(itemView);
itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
callback.onItemClick(getAdapterPosition());
}
});
mTextView = (TextView) itemView.findViewById(R.id.mTextView);
}
Now, when initializing the recycler adapter in an activity/fragment, just Create a new 'ClickCallback' (interface)
String[] values = {"Hello","World"};
RecyclerAdapter recyclerAdapter = new RecyclerAdapter(values, new RecyclerAdapter.ClickCallback() {
@Override
public void onItemClick(int position) {
// Do anything with the item position
}
});
That's it for me. :)
Set your onClickListener
s on onBindViewHolder()
and you can access the position from there. If you set them in your ViewHolder
you won't know what position was clicked unless you also pass the position into the ViewHolder
EDIT
As pskink
pointed out ViewHolder
has a getPosition()
so the way you were originally doing it was correct.
When the view is clicked you can use getPosition()
in your ViewHolder
and it returns the position
Update
getPosition()
is now deprecated and replaced with getAdapterPosition()
Update 2020
getAdapterPosition()
is now deprecated and replaced with getAbsoluteAdapterPosition()
or getBindingAdapterPosition()
Kotlin code:
override fun onBindViewHolder(holder: MyHolder, position: Int) {
// - get element from your dataset at this position
val item = myDataset.get(holder.absoluteAdapterPosition)
}
public static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
FrameLayout root;
public ViewHolder(View itemView) {
super(itemView);
root = (FrameLayout) itemView.findViewById(R.id.root);
root.setOnClickListener(this);
}
@Override
public void onClick(View v) {
LogUtils.errorLog("POS_CLICKED: ",""+getAdapterPosition());
}
}
A different method - using setTag() and getTag() methods of the View class.
use setTag() in the onBindViewHolder method of your adapter
@Override
public void onBindViewHolder(myViewHolder viewHolder, int position) {
viewHolder.mCardView.setTag(position);
}
where mCardView is defined in the myViewHolder class
private class myViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
public View mCardView;
public myViewHolder(View view) {
super(view);
mCardView = (CardView) view.findViewById(R.id.card_view);
mCardView.setOnClickListener(this);
}
}
use getTag() in your OnClickListener implementation
@Override
public void onClick(View view) {
int position = (int) view.getTag();
//display toast with position of cardview in recyclerview list upon click
Toast.makeText(view.getContext(),Integer.toString(position),Toast.LENGTH_SHORT).show();
}
see https://stackoverflow.com/a/33027953/4658957 for more details
@Override
public void onClick(View v) {
int pos = getAdapterPosition();
}
Simple as that, on ViewHolder