Save state of the item selected in RecyclerView when view is reused while scrolling
Asked Answered
Z

2

2

I have created an Adapter and ViewHolder for the recyclerView. I bind the imageButton of the itemView inside the Viewholder. And have set an onClickListener inside the onBindViewHolder.

Everything works as expected but the issue is now when i scroll down the list the selected state of the imageButton changes for the selected item and some of the items on the bottom of the list already appear selected.

Here is the some code

public class ListViewHolder extends RecyclerView.ViewHolder {
    TextView textViewUserName;
    ImageButton imageButtonCheckMark;

    public ListViewHolder(View itemView) {
        super(itemView);
        textViewUserName = (TextView) itemView.findViewById(R.id.textView_user_name);
        imageButtonCheckMark = (ImageButton) itemView.findViewById(R.id.imageButton_add_user);
    }
}

Adapter class

public class ListAdapter extends RecyclerView.Adapter<ListAdapter.ListViewHolder> {

    private LayoutInflater inflater;
    private Context context;
    private List<Metadata> list;
    public static boolean isUserSelected = false;
    ListInterface listener;

    public ListAdapter(Context context, List<Metadata> data, ListInterface listener) {
        Log.d(TAG, "Passed list to adapter : " + data.size());
        inflater = LayoutInflater.from(context);
        this.context = context;
        this.list = data;
        this.listener = listener;
    }

    @Override
    public ListViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = inflater.inflate(R.layout.item_following_people, parent, false);
        return new ListViewHolder(view);
    }

    @Override
    public void onBindViewHolder(ListViewHolder holder, int position) {

        holder.textViewUserName.setText(list.get(position).name);

        holder.imageButtonCheckMark.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (!isUserSelected) {
                    holder.imageButtonCheckMark.setImageResource(R.drawable.checkmark_green);
                    isUserSelected = true;
                } else {
                    holder.imageButtonCheckMark.setImageResource(R.drawable.checkmark_grey);
                    isUserSelected = false;
                }
                listener.onUserSelected(isUserSelected, holder.getLayoutPosition());
            }
        });
    }


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

Inteface class

public interface ListInterface {
    public void onUserSelected(boolean userStatus, int listPosition);
}

Interface callback listener inside activity

// Interface callback listener implemented in the activity class
private ArrayList<Metadata> metadataList = new ArrayList<>();
ArrayList<String> selectedUserIdList = new ArrayList<>();

@Override
public void onUserSelected(boolean isUserSelected, int pos) {
    if (isUserSelected) {
        Log.d(TAG, "Selected user Id: " + metadataList.get(pos).userID);
        followersSelectedIdList.add(metadataList.get(pos).userID);
    } else {
        Log.d(TAG, "Removed user Id: " + metadataList.get(pos).userID);
        followersSelectedIdList.remove(metadataList.get(pos).userID);
    }
}
Zennie answered 19/10, 2016 at 22:0 Comment(0)
H
0

You see this behavior because views are reused (recycled) as you scroll. You need to save the state for all buttons in the list and set the state on each button in onBindViewHolder() as it becomes visible.

Hooks answered 19/10, 2016 at 22:9 Comment(5)
I know about the reusing of itemViews in recyclerView. Can you please share some idea on how to save the state and set the states of the button. Any article/code snippet would be really helpful. I have tried various solution in SO of making a global variable ,etc but nothing seems to work. I found 2 libraries as well but they are for more complex functionality and i don't want to add a 3rd party dependencies for this simple problem.Zennie
@gaurav4sarma you already gave the code to set the button state. The problem is that you only have one boolean variable for the entire list when you need one for each button. A List<Boolean> will do the job nicely.Hooks
I am sorry but i am not able to implement it correctly can you please edit your answer and guide me as how to do implement it correctly ?Zennie
@gaurav4sarma you should post a new question showing what you tried and explaining what happens when you compile and run your code.Hooks
@gaurav4sarma you can include that link in your new question as long as you also provide details from your own code.Hooks
H
1

Add one attribute in your model class that will save the state as your button is selected or not, write code in onBindViewHolder() to manage button view like this,

if(yourModel.getIsSelected()){
   // positive view
} else { 
   //negative view
} 
Halfwitted answered 25/10, 2016 at 6:57 Comment(0)
H
0

You see this behavior because views are reused (recycled) as you scroll. You need to save the state for all buttons in the list and set the state on each button in onBindViewHolder() as it becomes visible.

Hooks answered 19/10, 2016 at 22:9 Comment(5)
I know about the reusing of itemViews in recyclerView. Can you please share some idea on how to save the state and set the states of the button. Any article/code snippet would be really helpful. I have tried various solution in SO of making a global variable ,etc but nothing seems to work. I found 2 libraries as well but they are for more complex functionality and i don't want to add a 3rd party dependencies for this simple problem.Zennie
@gaurav4sarma you already gave the code to set the button state. The problem is that you only have one boolean variable for the entire list when you need one for each button. A List<Boolean> will do the job nicely.Hooks
I am sorry but i am not able to implement it correctly can you please edit your answer and guide me as how to do implement it correctly ?Zennie
@gaurav4sarma you should post a new question showing what you tried and explaining what happens when you compile and run your code.Hooks
@gaurav4sarma you can include that link in your new question as long as you also provide details from your own code.Hooks

© 2022 - 2024 — McMap. All rights reserved.