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:
Get focused child, and use it to get position in adapter.
mRecyclerView.getChildAdapterPosition(mRecyclerView.getFocusedChild())
To complement @tyczj answer:
Generic Adapter Pseido code:
public abstract class GenericRecycleAdapter<T, K extends RecyclerView.ViewHolder> extends RecyclerView.Adapter{
private List<T> mList;
//default implementation code
public abstract int getLayout();
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext())
.inflate(getLayout(), parent, false);
return getCustomHolder(v);
}
public Holders.TextImageHolder getCustomHolder(View v) {
return new Holders.TextImageHolder(v){
@Override
public void onClick(View v) {
onItem(mList.get(this.getAdapterPosition()));
}
};
}
abstract void onItem(T t);
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
onSet(mList.get(position), (K) holder);
}
public abstract void onSet(T item, K holder);
}
ViewHolder:
public class Holders {
public static class TextImageHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
public TextView text;
public TextImageHolder(View itemView) {
super(itemView);
text = (TextView) itemView.findViewById(R.id.text);
text.setOnClickListener(this);
}
@Override
public void onClick(View v) {
}
}
}
Adapter usage:
public class CategoriesAdapter extends GenericRecycleAdapter<Category, Holders.TextImageHolder> {
public CategoriesAdapter(List<Category> list, Context context) {
super(list, context);
}
@Override
void onItem(Category category) {
}
@Override
public int getLayout() {
return R.layout.categories_row;
}
@Override
public void onSet(Category item, Holders.TextImageHolder holder) {
}
}
I solved this way
class MyOnClickListener implements View.OnClickListener {
@Override
public void onClick(View v) {
int itemPosition = mRecyclerView.getChildAdapterPosition(v);
myResult = results.get(itemPosition);
}
}
And in the adapter
@Override
public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_wifi, parent, false);
v.setOnClickListener(new MyOnClickListener());
ViewHolder vh = new ViewHolder(v);
return vh;
}
When using data binding and you need to know a RecyclerView click position from inside of an item's click listener:
Kotlin
val recyclerView = view.parent as RecyclerView
val position = recyclerView.getChildAdapterPosition(view)
I think the most correct way to get item position is
View.OnClickListener onClickListener = new View.OnClickListener() {
@Override public void onClick(View v) {
View view = v;
View parent = (View) v.getParent();
while (!(parent instanceof RecyclerView)){
view=parent;
parent = (View) parent.getParent();
}
int position = recyclerView.getChildAdapterPosition(view);
}
Because view, you click not always the root view of your row layout. If view is not a root one (e.g buttons), you will get Class cast exception. Thus at first we need to find the view, which is the a dirrect child of you reciclerview. Then, find position using recyclerView.getChildAdapterPosition(view);
onBindViewHolder() is called for each and every item and setting the click listener inside onBindVieHolder() is an unnecessary option to repeat when you can call it once in your ViewHolder constructor.
public class MyViewHolder extends RecyclerView.ViewHolder
implements View.OnClickListener{
public final TextView textView;
public MyViewHolder(View view){
textView = (TextView) view.findViewById(R.id.text_view);
view.setOnClickListener(this);
// getAdapterPosition() retrieves the position here.
}
@Override
public void onClick(View v){
// Clicked on item
Toast.makeText(mContext, "Clicked on position: " + getAdapterPosition(), Toast.LENGTH_SHORT).show();
}
}