user3422607
user3422607

Reputation:

wrong item changes in recyclerview

Hi everyone I'm stuck in this and need help :

Each item has a CheckBox and I set setOnLongClickListener for root element of my items in RecyclerView like this :

    holder.faviorateVideoItemRelative.setOnLongClickListener(new View.OnLongClickListener() {
        public boolean onLongClick(View arg0) {


            if (chk_visible)
            {
                return  true ;
            }
            holder.chk_faviorateVideo.setChecked(!holder.chk_faviorateVideo.isChecked());
            chk_visible = true ;
            checkedItemsCNT = 1 ;
            deleteListVideoCourses.add(data.get(holder.getAdapterPosition())) ;
            notifyDataSetChanged() ;
            return  true ;
        }
    });

If I scroll down , when I make a long click on one of items , the CheckBox of wrong item get checked !

Upvotes: 8

Views: 4285

Answers (6)

mahamrauf
mahamrauf

Reputation: 21

After using the above mentioned solutions,

The following solutions worked like a charm for me.

 @Override
public long getItemId(int position) {
    return position;
}

@Override
public int getItemViewType(int position) {
    return position;
}

using holder.setIsRecyclable(false) removes the desired selection as well when you come back to it after the whole scrolling process.

Upvotes: 0

user4696837
user4696837

Reputation:

It because as you use RecycleView it reuse your view every time when you scroll. RecycleView reuse your resource like this enter image description here

So when you scroll it's showing the wrong state of your view

Solution

If you write any logic for check-in onBindViewHolder then you have to use both part for true and false

if(yourCondition){
   //code if condition is true
}else {
   //code if condition is false
}

Other Solution

Simply you can solve it just using one statement to stop your RecycleView to reuse your view state like this

@Override
public void onBindViewHolder(ReqNotificationAdapter.MyViewHolder holder, int position) {

    holder.setIsRecyclable(false);
    //.................your other code
}

I use it to solve my problem.. hope it will solve yours if you don't have a problem stop Recycling with your purpose.

Upvotes: 19

Ahmad Aghazadeh
Ahmad Aghazadeh

Reputation: 17131

Solution 1:

You can override two method getItemId, getItemViewType.

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public int getItemViewType(int position) {
        return position;
    }

Like this:

public class EasyAdapter  extends RecyclerView.Adapter<EasyAdapter.ViewHolder>{


    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public int getItemViewType(int position) {
        return position;
    }
}

Solution 2: Set setIsRecyclable false.

EasyAdapter easyAdapter=new EasyAdapter();
easyAdapter.setIsRecyclable(false);

Upvotes: 1

J-Jamet
J-Jamet

Reputation: 857

When you initialize your OnLongClickListener, it is reused in views when they are no longer visible because they are cached. To solve the worry, create a new class to explicitly link an object to a listener and not just the view. For example :

private class BufferVideoLongClickListener implements View.OnLongClickListener {

    private VideoObject video; // And other stuff like checked, etc

    BufferVideoLongClickListener(VideoObject video, ...) {
        this.video = video;
        ...
    }

    @Override
    public void onLongClick(View view) {
        // Do your check and other things
        if(checked)
          ...
    }
}

And in your onBindViewHolder :

holder.faviorateVideoItemRelative.setOnLongClickListener(new BufferVideoLongClickListener(video, ...));

Upvotes: 0

IAmGroot
IAmGroot

Reputation: 13865

Could be an issue in your bind rather than setting of the value.

A common mistakes is not un-checking the view in the bind.

Make sure where you are setting checked, you have an else statement and set it to unchecked.

RecyclerView and Listview reuse views as they scroll, which includes any previously checked boxes. So it is important to un-check them if appropriate.

public void bindView(View view,   ..... //varies on implementation. rough idea.
{
  CheckBox mycheckbox = (CheckBox)view.findViewById(R.id.myidofcheckbox);


  int pos = view.getPosition();

  if(pos == 1) //example
     mycheckbox.setChecked(true);
  else
     mycheckbox.setChecked(false);

Upvotes: 1

Vishal Chhodwani
Vishal Chhodwani

Reputation: 2577

Yes it happens with ListView and RecyclerView

Try this code,

 holder.faviorateVideoItemRelative.setTag(position);
 holder.faviorateVideoItemRelative.setOnLongClickListener(new View.OnLongClickListener() {
    public boolean onLongClick(View arg0) {

        int tempPos = (int)holder.faviorateVideoItemRelative.getTag();

        if (chk_visible)
        {
            return  true ;
        }

         if(!holder.chk_faviorateVideo.isChecked())
         {
             holder.chk_faviorateVideo.setChecked(true);
         }
         else
         {
             holder.chk_faviorateVideo.setChecked(false);
         }

    holder.chk_faviorateVideo.setChecked(!holder.chk_faviorateVideo.isChecked());
        chk_visible = true ;
        checkedItemsCNT = 1 ;
        deleteListVideoCourses.add(data.get(tempPos)) ;
        notifyDataSetChanged() ;
        return  true ;
    }
});

Hope it will help you.

Upvotes: 0

Related Questions