Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting position of View in onCreateViewHolder

Tags:

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);         }     } } 
like image 379
Thomas Mohr Avatar asked Apr 24 '15 06:04

Thomas Mohr


People also ask

What is ViewGroup in onCreateViewHolder?

It represents the ViewGroup into which the new View will be added after it is bound to an adapter position. That means the parent of the view to be added.

How many times onCreateViewHolder called?

By default it have 5.

What is the difference between onCreateViewHolder and onBindViewHolder?

When used, pass the child Class Object, and in onCreateViewHolder , use Reflection to create the child ViewHolder. When you get an onBindViewHolder, just pass it to the ViewHolder.


2 Answers

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.

like image 166
yigit Avatar answered Nov 14 '22 06:11

yigit


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  } 
like image 20
Kakashi Avatar answered Nov 14 '22 07:11

Kakashi