Getting position of View in onCreateViewHolder
Solution 1
You cannot use the position
parameter of onBindViewHolder
in a callback.
If a new item is added above, RecyclerView will not rebind your item so the position is obsolete.
Instead, RecyclerView provides a getAdapterPosition
method on the ViewHolder.
@Override
public ViewHolder onCreateViewHolder(final ViewGroup parent, int viewType) {
final View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.single_line_row, parent, false);
final ViewHolder holder = new ViewHolder(view);
view.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
final int position = holder.getAdapterPosition();
if (position != RecyclerView.NO_POSITION) {
remove(mCommentList.get(position));
}
}
});
return holder;
}
I've added position != RecyclerView.NO_POSITION
check because when item is removed, RecyclerView will fade out the View so it may still be clicked by the user but its adapter position will return NO_POSITION
.
Solution 2
you can create a method to update position in your class.
in my case I need to attach watcher
and get the position to update arraylist
. here is the example:
class DodolWatcher bla bla {
private var position: Int = 0
fun updatePosition(pos:Int)
{
position = pos
}
override fun onTextChanged(charSequence: CharSequence, i: Int, i2: Int, i3: Int) {
Log.d("test", position.toString())
}
}
and in your onCreateViewHolder
you can attach watcher to edittext
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RVPaymentMethodAdapter.ViewHolder {
....
bla bla
....
theWatcher = DodolWatcher() <-- this is the trick
amount.addTextChangedListener(theWatcher)
}
and you will able to update position in your bindViewHolder
like this:
override fun onBindViewHolder(viewHolder: RVPaymentMethodAdapter.ViewHolder, position: Int) {
theWatcher.updatePosition(viewHolder.adapterPosition) <-- this is the trick
}
Related videos on Youtube
![Thomas Mohr](https://i.stack.imgur.com/dYcD4.jpg?s=256&g=1)
Thomas Mohr
Updated on July 09, 2022Comments
-
Thomas Mohr almost 2 years
I am using a RecyclerView with a single row layout with an ImageView and a TextView.
I want to implement a OnClickListener for the View and not for seperate ViewHolder objects. How can i get the position of the view in the Adapter?
Right now i'm deleting comments on click, but i cannot select the clicked View. I added a TODO in the appropriate line.
public class CommentAdapter extends RecyclerView.Adapter<CommentAdapter.ViewHolder> { /** List of Comment objects */ private List<Comment> mCommentList; /** Database with Comment objects */ private CommentsDataSource mDataSource; /** * Construcutor for CommentAdapter * * @param commentList List of Comment objects * @param dataSource Database with Comment objects */ public CommentAdapter(List<Comment> commentList, CommentsDataSource dataSource) { this.mCommentList = commentList; this.mDataSource = dataSource; } /** * Add Comment objects to RecyclerView * * @param position The position where the Comment object is added * @param comment Comment Object */ public void add(int position, Comment comment) { mCommentList.add(position, comment); notifyItemInserted(position); } /** * Remove Comment objects from RecyclerView * * @param comment Comment Object */ public void remove(Comment comment) { int position = mCommentList.indexOf(comment); // Avoid double tap remove if (position != -1) { mCommentList.remove(position); mDataSource.deleteComment(comment); notifyItemRemoved(position); } } @Override public ViewHolder onCreateViewHolder(final ViewGroup parent, int viewType) { final View view = LayoutInflater.from(parent.getContext()) .inflate(R.layout.single_line_row, parent, false); view.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // TODO get position remove(mCommentList.get(getItemCount() - 1)); } }); return new ViewHolder(view); } @Override public void onBindViewHolder(ViewHolder holder, int position) { final Comment comment = mCommentList.get(position); holder.comment.setText(comment.getComment()); } @Override public int getItemCount() { return mCommentList.size(); } public static class ViewHolder extends RecyclerView.ViewHolder { /** ImageView icon */ public ImageView icon; /** TextView comment */ public TextView comment; /** * Constructor for ViewHolder * * @param itemView Layout for each row of RecyclerView */ public ViewHolder(final View itemView) { super(itemView); icon = (ImageView) itemView.findViewById(R.id.icon); comment = (TextView) itemView.findViewById(R.id.comment); } } }
-
pskink about 9 yearsyou should really set your OnClickListener in ViewHolder(final View itemView) constructor, in that case ViewHolder should implement OnClickListener
-
-
Axay Prajapati about 7 yearsWhatever I click, I am getting position -1 (RecyclerView.NO_POSITION), what will be the issue?
-
starkej2 almost 7 yearsDon't do this - it will make the Adapter create a new view for every item in your list rather than recycle them, since it will think they are all different types.
-
Irfan about 5 yearsbad way to do it.
-
Neph over 4 yearsDoes it matter if you set the
OnClickListener
on theview
or theholder
? I linked it to the holder first, then changed it to the view after seeing this answer but it didn't seem to actually make a difference - at least not with a RecycleView that wasn't scrollable (not enough items for that).