Reputation: 3
I would really appreciate your help and guidance, regarding this simple issue.
I have a RecyclerView that has a list of movies. I would like to create a dynamic list, that can add some movies from a catalog.
The thing is that when I add the event for the button click, since the holder gets binded several times, the event gets attached several times. I do not know how to use the SetOnClickListener tecnique because I need the holder.AdapterPosition to know where should the new item should be added. I pass it as an extra to the MovieCatalogActivity and then send it back to the activity that holds the RecyclerView.
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using AndroidX.RecyclerView.Widget;
using Java.Util;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Supers.Adapters
{
public class adap_rv : RecyclerView.Adapter
{
public List<ItemMovies> data;
Context context;
public adap_rv(List<ItemMovies> listOfMovies, Context _context)
{
data = listOfMovies;
context = _context;
}
public override RecyclerView.ViewHolder OnCreateViewHolder(ViewGroup parent, int viewType)
{
View itemView = LayoutInflater.From(parent.Context).Inflate(Resource.Layout.elem_ReviewMovies, parent, false);
ViewHolderRR vh = new ViewHolderRR(itemView);
return vh;
}
public override void OnBindViewHolder(RecyclerView.ViewHolder holder, int position)
{
ViewHolderRR vh = holder as ViewHolderRR;
vh.imAddBefore.Click += delegate
{
ShowMovieCatalog(holder.AdapterPosition);
};
vh.imAddAfter.Click += delegate
{
ShowMovieCatalog(holder.AdapterPosition + 1);
};
vh.tvName.Text = data[position].Name;
}
public override int ItemCount
{
get { return data.Count; }
}
public void OnItemMove(int fromPosition, int toPosition)
{
data.Swap(fromPosition, toPosition);
NotifyItemMoved(fromPosition, toPosition);
}
public void OnItemDismiss(int position)
{
data.RemoveAt(position);
NotifyItemRemoved(position);
}
public void AddItem(int position, ItemMovies movie)
{
if (position > data.Count)
{
data.Add(movie);
}
else
{
data.Insert(position, movie);
}
NotifyItemInserted(position);
}
void ShowMovieCatalog(int position)
{
Intent intent = new Intent(context, typeof(Act_frmMovieCatalog));
intent.PutExtra(Enums.INTENTEXTRAS.INT_POSITIONITEM.ToString(), position);
((Activity)context).StartActivityForResult(intent, 100);
}
}
public class ViewHolderRR : RecyclerView.ViewHolder
{
public TextView tvName { get; private set; }
public ImageButton imAddBefore { get; private set; }
public ImageButton imAddAfter { get; private set; }
public ViewHolderRR(View itemView) : base(itemView)
{
imAddBefore = itemView.FindViewById<ImageButton>(Resource.Id.elem_btnAddBefore);
imAddAfter = itemView.FindViewById<ImageButton>(Resource.Id.elem_btnAddAfter);
}
}
}
Maybe if I listen to events from inside the ViewHolder, but I can't find examples.
Upvotes: 0
Views: 377
Reputation: 13833
If you want to add new Item when clicking the Button in the item layout, you can refer to the following code:
public override void OnBindViewHolder(RecyclerView.ViewHolder holder, int position)
{
ViewHolderRR vh = holder as ViewHolderRR;
// vh.imAddBefore.Click += delegate
//{
// ShowMovieCatalog(holder.AdapterPosition);
//};
// other code
vh.imAddBefore.SetOnClickListener(new MyAddItemBefore(position));
}
MyAddItemBefore.cs
(Photo
is my item model, you can change to yours)
class MyAddItemBefore : Java.Lang.Object, View.IOnClickListener
{
Photo item;
int position;
public MyAddItemBefore( int position) {
this.item= new Photo();
this.position = position;
}
public void OnClick(View v)
{
item.mCaption = "test";
data.Insert(position, item);
adapter.NotifyDataSetChanged();
}
}
Note:
imAddAfter
is implemented in a similar way.
And if you want to return position
to your activity, you can add a EventHandler
in your RecyclerView.Adapter(adap_rv
).
public event EventHandler<int> ItemClick;
// Raise an event when the item-click takes place:
void OnClick(int position)
{
if (ItemClick != null)
ItemClick(this, position);
}
And in method OnCreateViewHolder
public override RecyclerView.ViewHolder OnCreateViewHolder(ViewGroup parent, int viewType)
{
View itemView = LayoutInflater.From(parent.Context).Inflate(Resource.Layout.elem_ReviewMovies, parent, false);
// pass `OnClick` to Your ViewHolder
ViewHolderRR vh = new ViewHolderRR(itemView,OnClick);
return vh;
}
And in your ViewHolderRR.cs
public ViewHolderRR(View itemView, Action<int> listener) : base(itemView)
{
// other code
imAddBefore = itemView.FindViewById<Button>(Resource.Id.AddBeforeBtn);
// Detect user clicks on the item view and report which item
// was clicked (by layout position) to the listener:
imAddBefore.Click += (sender, e) => listener(base.LayoutPosition);
}
In your activity,add the following code:
// mAdapter is the instance of your RecyclerView.Adapter (`adap_rv `)
mAdapter.ItemClick += OnItemClick;
void OnItemClick(object sender, int position)
{
int itemNum = position + 1;
System.Diagnostics.Debug.WriteLine("clicked position = " + itemNum);
}
Upvotes: 0