Yashdeep Raj
Yashdeep Raj

Reputation: 1051

Xamarin RecyclerView Click event getting multiple context

I am creating a timeline feed using recyclerview in xamarin that contains item having multiple click event(child click) in a single item at different position (like youtube). so as implemented in case of recyclerview, I have define click event inside adapter at onBind method. Everything is working fine but after swiping the list up or down and then click fireup the multiple event by getting the context of all those item which was at that position of click.

Suppose at the launching of app item2 was at center (where we will click), then we swipe up and get the item4 at center and again swipe down we get item3 at center, at last click item3 (center position). and We get result of click event for all items which was at that position. it means item2, item3 and item4 click event get fired parallel.

Below is the code of myadapter-

public class RecyclerAdapter : RecyclerView.Adapter
{
    private List<Article> mArticle;
    private Context mContext;
    public RecyclerAdapter(List<Article> articles, Context context)
    {
        mArticle = articles;
        mContext = context;
    }
    public class MyView : RecyclerView.ViewHolder
    {
        public View mMainView { get; set; }
        public CircleImageView mauthor { get; set; }
        public ImageView mthumb { get; set; }
        public TextView mname { get; set; }
        public TextView title { get; set; }
        public CardView post_card { get; set; }
        public MyView(View view) : base(view)
        {
            mMainView = view;
        }

    }
    public override RecyclerView.ViewHolder OnCreateViewHolder(ViewGroup parent, int viewType)
    {
        View row = LayoutInflater.From(parent.Context).Inflate(Resource.Layout.post_card, parent, false);
        CircleImageView mauthorimg = row.FindViewById<CircleImageView>(Resource.Id.post_card_profile);
        ImageView mthumbimg = row.FindViewById<ImageView>(Resource.Id.thumbimg);
        TextView mauthorname = row.FindViewById<TextView>(Resource.Id.post_card_author_name);
        TextView articletitle = row.FindViewById<TextView>(Resource.Id.post_title);
        CardView mcard = row.FindViewById<CardView>(Resource.Id.post_card);


        MyView view = new MyView(row)
        {

            mauthor = mauthorimg,
            mthumb = mthumbimg,
            mname = mauthorname,
            title = articletitle,
            post_card = mcard

        };

        return view;
    }

    public override void OnBindViewHolder(RecyclerView.ViewHolder holder, int position)
    {
        MyView myholder = holder as MyView;
        myholder.title.Text = mArticle[position].title;

        if(mArticle[position].thumbimg !=null && mArticle[position].thumbimg != "")
        {
            byte[] thumbimage = Convert.FromBase64String(mArticle[position].thumbimg);
            myholder.mthumb.SetImageBitmap(BitmapFactory.DecodeByteArray(thumbimage, 0, thumbimage.Length));
        }
        else
        {
            myholder.mthumb.SetImageResource(Resource.Drawable.skull);
        }


        if (mArticle[position].author.profileimg != null && mArticle[position].author.profileimg != "")
        {
            byte[] profileimage = Convert.FromBase64String(mArticle[position].author.profileimg);
            myholder.mauthor.SetImageBitmap(BitmapFactory.DecodeByteArray(profileimage, 0, profileimage.Length));
        }
        else
        {

            myholder.mauthor.SetImageResource(Resource.Drawable.profile);
        }

        myholder.mname.Text = mArticle[position].author.name+" "+ mArticle[position].category+" "+ mArticle[position].date;
        myholder.mauthor.Click += (s, e) => { OpenArticle(mArticle[position]._id); };
        myholder.mMainView.Click += (s, e) => {
            OpenArticle(mArticle[position]._id);
        };
        myholder.title.Click += (s, e) => {
            OpenArticle(mArticle[position]._id); 
        };
            myholder.mauthor.Click += (s, e) => {
            if (mArticle[position].author._id!="" && mArticle[position].author._id!=null)
            {
                Intent intent = new Intent(mContext, typeof(Profile_Any_Activity));
                intent.PutExtra("_id", mArticle[position].author._id);
                mContext.StartActivity(intent);
            }

        };


    }

    private void OpenArticle(string id)
    {
        Intent intent = new Intent(mContext, typeof(Article_post));
        intent.PutExtra("_id", id);
        mContext.StartActivity(intent);
    }

    public override int ItemCount
    {
        get { return mArticle.Count; }
    }
}

Please suggest me the solution to fix this, Thank You.

Upvotes: 1

Views: 368

Answers (1)

Billy Liu
Billy Liu

Reputation: 2168

I think the reason is that you add the click event in OnBindViewHolder() method. Each time the row reappear in the screen the OnBindViewHolder() fired, and an extra click event is added to your view, so it will get multiple contexts.

You could use ClickListener instead and set position to tag of the view
For example:

public class RecyclerAdapter : RecyclerView.Adapter,View.IOnClickListener
{    
    ///
    ///Other Code
    ///

    public void OnClick(View v)
    {
        if(v.Id == Resource.Id.post_title)
        {
            OpenArticle(mArticle[(int)v.Tag]._id);
        }
        else if(v.Id == Resource.Id.post_card_author_name){
            //Do something
        }
        else
        {
            OpenArticle(mArticle[(int)v.Tag]._id);
        }            
    }  
}

And in OnBindViewHolder():

   public override void OnBindViewHolder(RecyclerView.ViewHolder holder, int position)
    {
        ///
        ///Other Code
        ///

        myholder.mMainView.SetOnClickListener(this);
        myholder.mMainView.Tag = position;
        myholder.title.SetOnClickListener(this);
        myholder.title.Tag = position;
    }

Upvotes: 2

Related Questions