Checkbox in Recyclerview Keeps on Checking Different Items

CheckBox in RecyclerView keeps on checking different items

That's an expected behavior. You are not setting your checkbox selected or not. You are selecting one and View holder keeps it selected. You can add a boolean variable into your ObjectIncome object and keep your item's selection status.

You may look at my example. You can do something like that:

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

private ArrayList<ObjectIncome> myItems = new ArrayList<>();

public AdapterTrashIncome(ArrayList<ObjectIncome> getItems, Context context){
try {
mContext = context;
myItems = getItems;
}catch (Exception e){
Log.e(FILE_NAME, "51: " + e.toString());
e.printStackTrace();
}
}

public class ViewHolder extends RecyclerView.ViewHolder {
public TextView tvContent;
public CheckBox cbSelect;

public ViewHolder(View v) {
super(v);
tvContent = (TextView) v.findViewById(R.id.tvContent);
cbSelect = (CheckBox) v.findViewById(R.id.cbSelect);
}
}

@Override
public void onBindViewHolder(ViewHolder holder, final int position) {
final ObjectIncome objIncome = myItems.get(position);
String content = "<b>lalalla</b>";
holder.tvContent.setText(Html.fromHtml(content));

//in some cases, it will prevent unwanted situations
holder.cbSelect.setOnCheckedChangeListener(null);

//if true, your checkbox will be selected, else unselected
holder.cbSelect.setChecked(objIncome.isSelected());

holder.cbSelect.setOnCheckedChangeListener(new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
//set your object's last status
objIncome.setSelected(isChecked);
}
});

}
}

Duplication in Checkbox selection in RecyclerView

The recycler view recycles the view in OnBindViewHolder.
So when items are clicked it gets reflected in some other positions.
To create a global SparseBooleanArray to store the clicked position.

private final SparseBooleanArray array=new SparseBooleanArray();

Then inside final viewholder add the clickListener and onClick store the position of the clicked item.

public class ViewHolder extends RecyclerView.ViewHolder {
public YOURVIEW view;
public ViewHolder(View v) {
super(v);
view = (YOURVIEW) v.findViewById(R.id.YOURVIEWID);
view.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
array.put(getAdapterPosition(),true);
notifyDataSetChanged();
}
});
}
}

And in inside OnBindViewHolder,

@Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
if(array.get(position)){
holder.followDiseaseCheckBox.setChecked(true);
}else{
holder.followDiseaseCheckBox.setChecked(false);
}
}

RecyclerView checks wrong items as i scroll down

As in the comment about the duplicate answer, your holder is retaining the check box view. You just need to update the check boxes state based on your backing data.

Add this before assigning the check listener in onBindViewHolder:

holder.check.setOnCheckedChangeListener(null);    
holder.check.setChecked(ActivityTeams.newList.contains(UserList.get(position));
holder.check.setOnCheckedChangeListener(new ... "you know what to do here"

Based on CompoundButton source code from here https://github.com/android/platform_frameworks_base/blob/master/core/java/android/widget/CompoundButton.java setChecked:

/**
* <p>Changes the checked state of this button.</p>
*
* @param checked true to check the button, false to uncheck it
*/
@Override
public void setChecked(boolean checked) {
if (mChecked != checked) {
mCheckedFromResource = false;
mChecked = checked;
refreshDrawableState();
notifyViewAccessibilityStateChangedIfNeeded(
AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);

// Avoid infinite recursions if setChecked() is called from a listener
if (mBroadcasting) {
return;
}

mBroadcasting = true;
if (mOnCheckedChangeListener != null) {
mOnCheckedChangeListener.onCheckedChanged(this, mChecked);
}
if (mOnCheckedChangeWidgetListener != null) {
mOnCheckedChangeWidgetListener.onCheckedChanged(this, mChecked);
}
final AutofillManager afm = mContext.getSystemService(AutofillManager.class);
if (afm != null) {
afm.notifyValueChanged(this);
}

mBroadcasting = false;
}
}

As you can see calling setChecked also calls the currently attached listener.

CheckBox States Keep Changing While Scrolling in Recycler View

Based on other Posts/Guides, this is how it works -

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

private ArrayList<StudentList> studentList;
private ArrayList<String> mRollNum;
private Activity activity;
private OnCheckBoxClickListener mListener;

private SparseBooleanArray itemStateArray = new SparseBooleanArray();

public interface OnCheckBoxClickListener {

void onCheckBoxClick(int position, boolean isChecked);
}

void setOnCheckBoxClickListener(OnCheckBoxClickListener listener){

mListener = listener;
}

class ViewHolder extends RecyclerView.ViewHolder {

private MaterialTextView studentName;
private MaterialTextView studentRoll;
private MaterialTextView attendanceStatus;
MaterialCheckBox mCheckbox;

ViewHolder(@NonNull View itemView, final OnCheckBoxClickListener listener) {
super(itemView);

studentName = itemView.findViewById(R.id.stdName);
studentRoll = itemView.findViewById(R.id.stdRoll);
attendanceStatus = itemView.findViewById(R.id.studentAttendance);
mCheckbox = itemView.findViewById(R.id.checkBox);

mCheckbox.setOnClickListener(new View.OnClickListener() {
@SuppressLint("SetTextI18n")
@Override
public void onClick(View view) {

int adapterPosition = getAdapterPosition();
if (!itemStateArray.get(adapterPosition, false)) {
attendanceStatus.setTextColor(Color.GREEN);
attendanceStatus.setText("Present");
mCheckbox.setChecked(true);
itemStateArray.put(adapterPosition, true);
listener.onCheckBoxClick(adapterPosition, true);

}
else {
mCheckbox.setChecked(false);
itemStateArray.put(adapterPosition, false);
listener.onCheckBoxClick(adapterPosition, false);
attendanceStatus.setTextColor(Color.RED);
attendanceStatus.setText("Absent");


}


}
});
}

@SuppressLint("SetTextI18n")
void bind(int position) {

if (!itemStateArray.get(position, false)) {
mCheckbox.setChecked(false);
attendanceStatus.setTextColor(Color.RED);
attendanceStatus.setText("Absent");

}
else {
attendanceStatus.setTextColor(Color.GREEN);
attendanceStatus.setText("Present");
mCheckbox.setChecked(true);

}
}
}

RecyclerViewAdapter(Activity activity, ArrayList<StudentList> mStudentList, ArrayList<String> rollNum ) {
studentList = mStudentList;
this.activity = activity;
this.mRollNum = rollNum;

}

@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {

View studentListView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.card_view, parent, false);

return new ViewHolder(studentListView, mListener);
}

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

StudentList currentStudent = studentList.get(position);

holder.studentName.setText(currentStudent.getStudName());
holder.studentRoll.setText(currentStudent.getStudRoll());

holder.bind(position);
}

@Override
public int getItemCount() {
return studentList == null ? 0 : studentList.size();
}

chekbox always checking last item in recyclerview

Maybe viewHolder reuse the previous item.Try to update listData, not currentItem.
And move the nested Listener

override fun onBindViewHolder(holder: SelectedListDateViewHolder, position: Int) {

holder.itemView.tvDateList.text = listDate[position].date
holder.checkBoxList.isChecked = listDate[position].isChecked
holder.checkBoxList.setOnClickListener {

listDate[position].isSelected = holder.checkBoxList.isChecked
}

holder.itemView.setOnClickListener {

holder.checkBoxList.isChecked = !holder.checkBoxList.isChecked
listDate[position].isSelected = holder.checkBoxList.isChecked

val currentItem = listDate[position]
if (holder.checkBoxList.isChecked) {

onItemCheckListener.onItemCheck(currentItem)

} else {

onItemCheckListener.onItemUncheck(currentItem)
}
}
}


Related Topics



Leave a reply



Submit