I know about recycling rows in a listview. I have a listview with toggle buttons. I'm saving the states of the toggle buttons in a SparseBooleanArray as lot of posts suggest. My problem is the toggle button row gets on and off on scroll anyway. In my code I have saved the state of togglebutton and their respective position in the array and them I get their states from the same array. Thanks.
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
View row = convertView;
final ViewHolderBrandAvailability holder;
if(row == null){
dbHelper = new DBHelper(con);
database = dbHelper.getWritableDatabase();
LayoutInflater mInflater = (LayoutInflater) con.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
//viewHolderBrandAvailability = new ViewHolderBrandAvailability();
row = mInflater.inflate(R.layout.brand_availability_listview, parent, false);
holder = new ViewHolderBrandAvailability();
holder.brandNameTextView = (TextView) row.findViewById(R.id.brandAvailabilityNameText);
holder.radioGroup = (ToggleButton) row.findViewById(R.id.brandAvailable);
/*viewHolderBrandAvailability.unavailableRadioBtn = (RadioButton) convertView.findViewById(R.id.brandUnavailable);*/
row.setTag(holder);
}else {
holder = (ViewHolderBrandAvailability) row.getTag();
}
holder.radioGroup.setTag(position);
holder.radioGroup.setChecked(mCheckStates.get(position, false));
holder.radioGroup.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean isChecked) {
if(isChecked){
selectedBrandStatus.put(((BrandAvailability)list.get(position)).getBrand_id(), "Yes");
}else {
selectedBrandStatus.put(((BrandAvailability)list.get(position)).getBrand_id(), "No");
}
mCheckStates.put((Integer) compoundButton.getTag(), isChecked);
}
});
String brandTitle = ((BrandAvailability)list.get(position)).getBrand_title();
holder.brandNameTextView.setText(brandTitle);
//holder.radioGroup.setChecked();
return row;
}
static class ViewHolderBrandAvailability {
private TextView brandNameTextView;
private ToggleButton radioGroup;
//RadioButton unavailableRadioBtn;
//int position;
}
From the code you've posted, I see nothing that indicates a problem with the checked state of the
ToggleButton
changing on scroll. In fact, I created my own adapter to test out your code, and it worked perfectly fine for me.Often, people run into a similar issue because they don't realize that the
OnCheckedChangeListener
they set in one call togetView()
will stick around during the next call togetView()
, and so thesetChecked()
call winds up triggering it. However, in your case, you're usingcompoundButton.getTag()
to determine the index into themCheckStates
array, so there's no problem here.That being said, you are using the
getView()
position
argument for other operations in your listener, and this will cause the issue I described above.Imagine
getView()
is called for the very first time, for position 0. Your code runs, and assigns the listener. You wind up checking theToggleButton
at position 0, so you callselectedBrandStatus.put(list.get(0).getBrand_id(), "Yes")
. Now you scroll the list until this view is recycled:getView()
is called again and this view is passed asconvertView
. Let's call this position 20. Your listener is still in place, so when theToggleButton
is unchecked byholder.radioGroup.setChecked(mCheckStates.get(20, false))
, it is triggered again. Now it will overwrite the previous"Yes"
with"No"
, since the listener was created usingposition
= 0.You can just change all of the indexes in your listener to be
(Integer) compoundButton.getTag()
and that will fix this problem.