0

I have the following AssessmentAdapter class. In the constructor of my ViewHolder class, I findViewById() to get the ImageView with the delete icon, and assign the click event to it.

I am trying to find the position of my ViewHolder, and send this to the parameterized constructor of my OnDeleteIconClicked class, but the position is always -1. Why?

Here is my code:

public class AssessmentAdapter extends RecyclerView.Adapter<AssessmentAdapter.AssessmentViewHolder> {

private List<Assessment> assessmentList;
private IAssessmentsList context;

public AssessmentAdapter(List<Assessment> assessmentList, IAssessmentsList context){
    this.assessmentList = assessmentList;
    this.context = context;
}

@Override
public AssessmentViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View rowView = LayoutInflater.from(parent.getContext())
            .inflate(R.layout.assessment_list_row, parent, false);

    rowView.setOnClickListener(new OnAdapterItemClicked());

    return new AssessmentViewHolder(rowView);
}

@Override
public void onBindViewHolder(AssessmentViewHolder holder, int position) {
    Assessment assessment = assessmentList.get(position);
    holder.txtClientName.setText(assessment.getClient());
    holder.txtAssessmentDate.setText(assessment.getInspectedDate());
    holder.imageView.setTag(assessment.getId());
}

@Override
public int getItemCount() {
    return assessmentList.size();
}

public class AssessmentViewHolder extends RecyclerView.ViewHolder{

    public TextView txtClientName, txtAssessmentDate;
    public ImageView imageView;

    public AssessmentViewHolder(View view){
        super(view);

        txtClientName = view.findViewById(R.id.txtClientName);
        txtAssessmentDate = view.findViewById(R.id.txtAssessmentDate);

        imageView= view.findViewById(R.id.deleteAssessment);
        int layoutPosition = getLayoutPosition(); //always -1
        int adapterPosition = getAdapterPosition(); //always -1
        imageView.setOnClickListener(new OnDeleteIconClicked(getAdapterPosition()));
    }
}

public class OnAdapterItemClicked implements View.OnClickListener{

    @Override
    public void onClick(View v) {
        context.OnAdapterItemClicked(v);
    }
}
public class OnDeleteIconClicked implements View.OnClickListener {

    private int position;

    public OnDeleteIconClicked(int position){
        this.position = position;
    }

    @Override
    public void onClick(View v) {
        context.OnDeleteItemClicked(Integer.parseInt(v.getTag().toString()), position);
    }

    public int getPosition() {
        return position;
    }
    public void setPosition(int position) {
        this.position = position;
    }
}
}
Phantômaxx
  • 37,901
  • 21
  • 84
  • 115

5 Answers5

3
imageView.setOnClickListener(new OnDeleteIconClicked(getAdapterPosition()));

Take the line above and place it inside onBindViewHolder like so:

@Override
public void onBindViewHolder(AssessmentViewHolder holder, int position) {
    Assessment assessment = assessmentList.get(position);
    holder.txtClientName.setText(assessment.getClient());
    holder.txtAssessmentDate.setText(assessment.getInspectedDate());
    holder.imageView.setTag(assessment.getId());
    holder.imageView.setOnClickListener(new OnDeleteIconClicked(position));
}
HaroldHibari
  • 422
  • 3
  • 12
  • 3
    You should avoid defining click events inside `onBindViewHolder()`, because onBindViewHolder() is called for each and every item and setting the click listener is an unnecessary option to repeat when you can call it once in your ViewHolder constructor. Read [here](https://stackoverflow.com/questions/33845846/why-is-adding-an-onclicklistener-inside-onbindviewholder-of-a-recyclerview-adapt?utm_medium=organic&utm_source=google_rich_qa&utm_campaign=google_rich_qa) for more. – Paresh P. Apr 10 '18 at 09:36
  • @Wizard Thanks for this, will update my code accordingly – android_monstertjie Apr 10 '18 at 11:23
1

but the position is always -1. Why?

getAdapterPosition(); It will always return -1 when recyclerview makes layout calculations. You are calling this methods inside ViewHolder.. It means RecyclerView is doing calculations.

If you need position inside click actions of view,

inside ViewHolder { ....
...
view.setOnClickListener(new View.OnClickListener) {
        @Override
        public void onClick(View v) {
             int position = getAdapterPosition(); // This does not return -1, because calculation is done and views have been inflated.
        }
    }
);
....
}
Paresh P.
  • 6,677
  • 1
  • 14
  • 26
  • Thanks for your explanation. I avoid setting my OnClickListeners as you have shown above, as to me personally, this makes my code look cluttered. – android_monstertjie Apr 10 '18 at 09:23
0
public class AssessmentViewHolder extends RecyclerView.ViewHolder {

public TextView txtClientName, txtAssessmentDate;
public ImageView imageView;

public AssessmentViewHolder(View view) {
 super(view);

 txtClientName = view.findViewById(R.id.txtClientName);
 txtAssessmentDate = view.findViewById(R.id.txtAssessmentDate);

 imageView = view.findViewById(R.id.deleteAssessment);
 int layoutPosition = getLayoutPosition(); //always -1
 int adapterPosition = getAdapterPosition(); //always -1

 // When intialise viewholder value of getAdapterPosition will be always -1
 // instead of passing value from constructor, get when onClick event occure
 imageView.setOnClickListener(new OnDeleteIconClicked()); 

} }

Change in OnDeleteIconClicked

public class OnDeleteIconClicked implements View.OnClickListener {

private int position;

@Override
public void onClick(View v) {
 this.position = getAdapterPosition();   
 context.OnDeleteItemClicked(Integer.parseInt(v.getTag().toString()), position);
}

public int getPosition() {
 return position;
}

}

Ganesh Tikone
  • 1,047
  • 1
  • 8
  • 15
0

Put your click event inside onBindViewHolder

holder.imageView.setOnClickListener(new OnDeleteIconClicked(position));
BonBon
  • 16
  • 4
0

getAdapterPosition(); It will always return -1 when recyclerview makes layout calculations. You are calling this methods inside ViewHolder.. It means RecyclerView is doing calculations.

If you need position inside click actions of view, call it in the public void onClick(final View v) method for example:

"@Override public void onBindViewHolder(@NonNull final ViewHolder holder, final int position) {

    final Students user = mUsers.get(position);
    holder.Name.setText(user.getFullname());
    holder.Index.setText(user.getIndex_number());


    if (user.getThumbnail().equals("default")) {
        holder.profile_image.setImageResource(R.drawable.profile_pic);
    } else {
        Picasso.get().load(user.getThumbnail())
                .placeholder(R.drawable.profile_pic)
                .into(holder.profile_image);
    }

  holder.itemView.setOnClickListener(new View.OnClickListener() {
       @Override
       public void onClick(final View v) {
           **list_user_id = mUsers.get(position).getId();**

           Intent Sub = new Intent(mContext, UserProfileActivity.class);
           Sub.putExtra("user_id1", list_user_id);
           mContext.startActivity(Sub);

BUT NOT

getAdapterPosition(); It will always return -1 when recyclerview makes layout calculations. You are calling this methods inside ViewHolder.. It means RecyclerView is doing calculations.

If you need position inside click actions of view, call it in the public void onClick(final View v) method for example:

@Override public void onBindViewHolder(@NonNull final ViewHolder holder, final int position) {

    final Students user = mUsers.get(position);
    holder.Name.setText(user.getFullname());
    holder.Index.setText(user.getIndex_number());

**list_user_id = mUsers.get(position).getId();**



    if (user.getThumbnail().equals("default")) {
        holder.profile_image.setImageResource(R.drawable.profile_pic);
    } else {
        Picasso.get().load(user.getThumbnail())
                .placeholder(R.drawable.profile_pic)
                .into(holder.profile_image);
    }

  holder.itemView.setOnClickListener(new View.OnClickListener() {
       @Override
       public void onClick(final View v) {

           Intent Sub = new Intent(mContext, UserProfileActivity.class);
           Sub.putExtra("user_id1", list_user_id);
           mContext.startActivity(Sub);