Welcome to the Treehouse Community
Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.
Looking to learn something new?
Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.
Start your free trialKevin Faust
15,353 Pointsrecyclerview and checkboxes
Hi
Due to recyclerview having the viewholder pattern, when a checbox is clicked and when you scroll down, there will be other boxes checked. I was wondering the way to go about this. StackOverflows solution have been too advanced and none of the solutions worked for me.
Thanks
4 Answers
Andrew Sheragy
16,379 PointsYes in the onBindViewHolder function put an onClickListener on the holder.checkDisBox. You'll also need to make a final int variable for the position so when the onClick is triggered it has the position available.
final int pos = position;
holder.checkDisBox.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
..update your numbers array at position "pos" to be checked or unchecked (opposite of current value)
}
});
Andrew Sheragy
16,379 PointsDoes your onBindViewHolder always set the checkbox to checked or unchecked? If not it will use its checked state from the previous view that used it.
Kevin Faust
15,353 PointsMy onBindViewHolder is just assigning text to a textfield. I haven't done anything to my checkboxes. I know that it's using the checked state from the previous view but I'm wondering how I can fix that / what one would usually do.
Ben Deitch
Treehouse TeacherYep, Andrew's right. You likely need to set either checked or unchecked explicitly each time a View is retrieved. I think you'll just have to keep track of which items are checked, and then use the getAdapterPosition method (or something like it) to get the position and then set checked vs not checked on each View as they get reused.
Kevin Faust
15,353 PointsCan you give an example using code of what you said? I dont know how to go about this with words alone. Thanks
Ben Deitch
Treehouse TeacherDoes this help? Looks like I initialize the Adapter with a List of Strings, and then use the position parameter in onBindViewHolder to determine the position and set the correct String. I don't think this ever had enough views to see any getting reused though. So I'm hesitant to say it's exactly what you're looking for.
Andrew Sheragy
16,379 PointsCan you paste the code for your RecyclerView.Adapter class?
Kevin Faust
15,353 Pointspublic class myAdapter extends RecyclerView.Adapter<myAdapter.ViewHolder> {
private List<numbers> mNumbers = Collections.emptyList();
public myAdapter (List<numbers> numbers) {
mNumbers = numbers;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_slot, parent, false);
ViewHolder vh = new ViewHolder(v);
return vh;
}
@Override
public void onBindViewHolder(ViewHolder holder, final int position) {
holder.bindNumbers(mNumbers.get(position));
}
@Override
public int getItemCount() {
return mNumbers.size();
}
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
TextView numberText;
EditText checklistText;
Button deleteButton;
CheckBox checkDisBox;
public ViewHolder(View itemView) {
super(itemView);
numberText = (TextView) itemView.findViewById(R.id.number);
checklistText = (EditText) itemView.findViewById(R.id.editText);
deleteButton = (Button) itemView.findViewById(R.id.deleteButton);
checkDisBox = (CheckBox) itemView.findViewById(R.id.checkBox);
deleteButton.setOnClickListener(this);
}
public void bindNumbers(numbers numbers) {
numberText.setText(numbers.getInt() + "");
}
@Override
public void onClick(View v) {
mNumbers.remove(getAdapterPosition());
notifyItemRemoved(getAdapterPosition());
}
}
}
Andrew Sheragy
16,379 PointsFor checking boxes you need an onClickListener to save the state of the checkbox, ignore that for right now there are still a few other things you can do to make some progress
- Add a boolean field to your numbers object to indicate if a box is checked, add getChecked() to return that field
- Temporarily initialize a few of these to "true" for testing purposes
- on bindNumbers add checkDisBox.setChecked(numbers.getChecked())
Then you can test the scrolling on your list and only the checkboxes in the positions you set as "true" should stay checked as they go on and off the screen.
The last step is to add an onClickListener to the checkbox so your numbers object in that position get updated to "true" when a box is checked and "false" when unchecked.
Kevin Faust
15,353 PointsI added a boolean field to my numbers object and initialized it as false. I created a getter and setter method for the boolean field. I added setChecked(numbers.getChecked()) in my bindNumbers method.
I didn't understand what to do after. I added an onclick listener to my checkbox but am unsure where exactly im supposed to put it. In the bindNumbers() method? Also im not sure what to put inside the onclick listener
Kevin Faust
15,353 PointsKevin Faust
15,353 PointsOh my goodness :O IT FINALLY WORKS!! I was staring at your answer for a while trying to see how that would work and I'm beginning to see what we did. Thank you for the help!