Checking a Checkbox in Listview Makes Other Random Checkboxes Checked Too

Checking a checkbox in listview makes other random checkboxes checked too

When a listview recycles views , it recycles its present state as well as listeners attached to it. In my example, if the checkbox was checked and has a onCheckedChangeListener set, both will remain a part of recycled view based on position. So it is our responsibility to reset all states and remove previous listeners.

So when I was unchecking the recycled view, the onCheckedChange listener was getting executed.
one line made the program work perfectly. The listener was removed by :

holder.ckbox.setOnCheckedChangeListener(null); 

Below is the working code of Adapter for people who may stumble upon this problem:

public class MyCustomAdapter extends ArrayAdapter<ApplicationInfo>  {

private List<ApplicationInfo> appInfoList;
private LayoutInflater mInflater;
private PackageManager pm;
ArrayList<Boolean> positionArray;
private Context ctx;
int[] visiblePosArray;
private volatile int positionCheck;

public MyCustomAdapter(Context context, List<ApplicationInfo> myList) {
super(context, NO_SELECTION);
appInfoList = myList;
ctx=context;
mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
pm = context.getPackageManager();

positionArray = new ArrayList<Boolean>(myList.size());
for(int i =0;i<myList.size();i++){
positionArray.add(false);
}
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return appInfoList.size();
}

@Override
public View getView(final int position, View convertView, ViewGroup parent) {

View row = convertView;
Holder holder = null;

if(row==null){
row = mInflater.inflate(R.layout.testlayout, null);
// visiblePosArray[position%visiblePosArray.length]=position;
holder = new Holder();
holder.appIcon = (ImageView)row.findViewById(R.id.imageView1);

holder.ckbox =(CheckBox)row.findViewById(R.id.checkBox1);

row.setTag(holder);
} else {

holder = (Holder) convertView.getTag();
holder.ckbox.setOnCheckedChangeListener(null);

}

holder.ckbox.setFocusable(false);
holder.appIcon.setImageDrawable(appInfoList.get(position).loadIcon(pm));
holder.ckbox.setChecked(positionArray.get(position));
holder.ckbox.setText(appInfoList.get(position).loadLabel(pm));
holder.ckbox.setOnCheckedChangeListener(new OnCheckedChangeListener() {

@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if(isChecked ){
System.out.println(position+"--- :)");
positionArray.set(position, true);

}else
positionArray.set(position, false);
}
});

return row;
}
static class Holder
{
ImageView appIcon;
CheckBox ckbox;

}

}

Checking a few CheckBoxes in a ListView results in checking another CheckBox

I fixed this after days of research and trying and this is the fix for everyone who stumbled upon the same problem:

holder.cbSet.setOnCheckedChangeListener(new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton button, boolean isChecked) {

if(isChecked)
mExercise.get(position).setCbChecked(true);
else
mExercise.get(position).setCbChecked(false);
}
});

holder.cbSet.setChecked(exercise.isCbChecked());

check box in listview not working properly

This is happening because of view recycling. What you need to do is maintain an array of say booleans and every time a checkbox is checked toggle the corresponding boolean. Then in your getview check the corresponding boolean array position and set the state of the check box.

Along these lines: I have modified it so it displays correctly. Have not checked what the rest of your code is upto. ^_^

public class CustomListViewAdapter extends ArrayAdapter<Client> {

ViewHolder holder = null;
private LayoutInflater inflator = null;
private ArrayList<Client> orderList = null;
ArrayList<View> allViews;

boolean[] checkedStates; //********** NEW ********

public CustomListViewAdapter(Context context, int resource,
List<Client> objects) {
super(context, resource, objects);

orderList = (ArrayList<Client>) objects;
inflator = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
allViews = new ArrayList<View>();

checkedStates = new boolean[objects.size()]; //********** NEW ********
}

@Override //********** NEW ******** position argument is now final
public View getView(final int position, View convertView, ViewGroup parent) {
if(convertView == null) {
convertView = inflator.inflate(R.layout.listview_add_order, null);
holder = new ViewHolder();
convertView.setTag(holder);
holder.txtViewName = (TextView) convertView.findViewById(R.id.txtViewAddOrder);
holder.spinnerAddorder = (Spinner) convertView.findViewById(R.id.spinnerAddOrder);
holder.checkAddorder = (CheckBox) convertView.findViewById(R.id.checkAddOrder);
holder.checkAddorder.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();

holder.checkAddorder.setTag(holder);
}

allViews.add(position, holder.spinnerAddorder);

holder.checkAddorder.setOnClickListener(new OnClickListener() {

@Override
public void onClick(View view) {

checkedStates[position] = !checkedStates[position]; //********** NEW ********
}
});

holder.chechAddorder.setChecked(checkedStates[position]); //********** NEW ********

List<String> list = new ArrayList<String>();
list.add("Select Quantity");
list.add("1");
list.add("2");
list.add("3");
ArrayAdapter<String> dataAdapter = new ArrayAdapter<String>(this.getContext(),R.layout.spinner_add_order_style, list);
dataAdapter.setDropDownViewResource(android.R.layout.simple_spinner_item);
holder.spinnerAddorder.setAdapter(dataAdapter);

if(checkedStates[position]) { //********** NEWEST ******** assuming true is checked and false is unchecked

ViewHolder checkPosition = (ViewHolder) holder.checkAddorder.getTag();
checkPosition.spinnerAddorder.setVisibility(View.VISIBLE);
} else {

ViewHolder checkPosition = (ViewHolder) holder.checkAddorder.getTag();
checkPosition.spinnerAddorder.setVisibility(View.INVISIBLE);
}

Client order = orderList.get(position);

holder.txtViewName.setText(order.getFirstName());
return convertView;
}

private static class ViewHolder {
public TextView txtViewName = null;
public Spinner spinnerAddorder = null;
public CheckBox checkAddorder = null;
}

}

Every seventh box checked with CheckBoxes in ListView

Hmmmm I think you misunderstood what the getChildCount() and getChildAt() methods do. Those will actually get only the rendered views. Unless I misread something here, if you have 650ish rows you cannot accomplish what you want with the views that are being rendered. Instead, you should implement an onItemClickListener (or, alternatively, something that fires when the checkboxes are clicked) and after the checkbox is checked, save that state into your model.

Android listview multiple items are checked while selecting a checkbox

You should be calling holder.box.setChecked(contact.isSelect()); instead of setSelected() to properly reset whether or not the CheckBox is checked.

The selected state does not impact whether or not the box is checked.



Related Topics



Leave a reply



Submit