Search code examples
androidandroid-recyclerviewonclicklistener

TextView inside Recyclerview ViewHolder - OnClickListner


I have a very simple RecyclerView and a ViewHolder as following

ViewHolder

 private class SENT_VH : RecyclerView.ViewHolder, View.IOnClickListener
    {
        public SENT_VH(View itemView) : base(itemView)
        {                
            MyText = itemView.FindViewById<TextView>(Resource.Id.sent_msg_time);
            DeleteButton = itemView.FindViewById<TextView>(Resource.Id.sent_msg_person_name);               
            itemView.SetOnClickListener(this);
        }           
        public TextView DeleteButton { get; set; }          
        public TextView MyText { get; set; }           

        public void OnClick(View v)
        {
            // ViewHolder Item clicked
        }          
    }

This work perfectly when I click on the item but I am trying to implement OnClickListner on DeleteButton as following

public override void OnBindViewHolder(RecyclerView.ViewHolder holder, int position)
    {
        try
        {
            SENT_VH viewHolder = holder as SENT_VH;                            
            viewHolder.MyText.Text = itemList[position].userText;
            viewHolder.DeleteButton.SetOnClickListener(new DeleteOnClickListner(itemList[position].id, context, position));
        }
        catch (Exception X)
        {
            //LOG.Error >> ERROR
        }
    }

Finally my DeleteOnClickListner is

  class DeleteOnClickListner : Java.Lang.Object, View.IOnClickListener
    {
        private decimal id;
        private Context context;
        private int pos;
        public DeleteOnClickListner(decimal id, Context context, int pos)
        {
            this.id = id;
            this.context = context;
            this.pos = pos;
        }
        public void OnClick(View v)
        {
            Android.Util.Log.Debug("ADAPTER", "Delete id: " + id);
            ((MainActivity)context).deleteConfirmation(id, pos);
        }
    }

In the MainActivity for deleteConfirmation method I am just trying to get the position and id as following

public void deleteConfirmation(decimal id, int pos)
 {
    EVENT_LOGGER(TAG, "Pos:" + pos + ", id: " + id);
 }

The problem is I always get the same id and position as the first DeleteButton I click in any ViewHolder, it never changes.

For example, if I first clicked on the DeleteButton at item position 10, it keeps sending position 10 no matter which DeleteButton I click next.

Do you guys have any idea what is going on

EDIT:

As suggested by @tyczj, I tried to move OnclickListner in my ViewHolder by adding the following in my ViewHolder

public void SetMyView(decimal id, Context context, int pos)
        {               
            DeleteButton.SetOnClickListener(new DeleteOnClickListner(id, context, pos));
        }

And Using SetMyView in my OnBindViewHolder as following

public override void OnBindViewHolder(RecyclerView.ViewHolder holder, int position)
{
    try
    {
        SENT_VH viewHolder = holder as SENT_VH;   
        viewHolder.SetMyView(position, context);  //This line here                       
        viewHolder.MyText.Text = itemList[position].userText;
        viewHolder.DeleteButton.SetOnClickListener(new DeleteOnClickListner(itemList[position].id, context, position));
    }

No Difference exactly the same result catch (Exception X) { //LOG.Error >> ERROR } }

EDIT 2 - Working Solution

I updated the VH to just add the following

DeleteButton.SetOnClickListener(new DeleteOnClickListner(AdapterPosition));

Solution

  • What is wrong with your first method? its much easier to to use the ViewHolder than what you are doing

    Make your viewholder an inner class of your adapter

    Kotlin example

    inner class ViewHolder(view: View): RecyclerView.ViewHolder(view){
        val MyText : TextView = view.findViewById(R.id.sent_msg_time)
        val DeleteButton : TextView = view.findViewById(R.id.sent_msg_person_name)
    
        init {
            DeleteButton .setOnClickListener {
                ((MainActivity)context).deleteConfirmation(itemList[adapterPosition].id, adapterPosition)
            }
        }
    }
    

    adapterPosition or absoluteAdapterPosition depending on the version of recyclerview you are using gives you the position of the viewholder

    for your adapter pass in context to get your main activity (should be using an interface though to communicate back to the activity) and the list of items then you can get what you need a lot easier