I have an ArrayAdapter for a list view that has multiple buttons in it. For one toggle button, I want to have a default state based on a condition, and let users toggle the button as well.
However, when users click button on row 1, the button for row 3 actually gets selected. I'm not sure why this is happening. Below is snippet of relevant code from my getView
method with comments.
layout of my toggle button
<ToggleButton android:id="@+id/color_toggle"
android:layout_width="50px"
android:layout_height="50px"
android:focusable="false"
android:textOn="" android:textOff="" android:layout_alignParentLeft="true"
android:layout_marginRight="10dp"
/>
class Color {
int id;
int something;
}
List<Color> colorsList;
class ColorHolder {
TextView colorNameText;
ToggleButton toggleButton;
}
public View getView(final int position, final View convertView, final ViewGroup parent) {
View rowView = convertView;
Color c = colorsList.get(position);
if (null == rowView) {
rowView = this.inflater.inflate(R.layout.list_item_color, parent, false);
holder = new ColorHolder();
holder.colorNameText = (TextView) rowView.findViewById(R.id.color_name);
holder.toggleButton = (ToggleButton) rowView.findViewById(R.id.color_toggle);
rowView.setTag(holder);
}
else {
holder = (ColorHolder)rowView.getTag();
}
holder.toggleButton.setTag(c.getId());
final ColorHolder thisRowHolder = holder;
holder.toggleButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (thisRowHolder.toggleButton.isChecked()) {
thisRowHolder.toggleButton.setBackgroundDrawable(//normal button);
thisRowHolder.toggleButton.setChecked(false);
for (int i = 0; i < colorList.size(); i++) {
if (colorList.get(i) == (Integer)v.getTag()) {
colorList.get(i).setSomething(0);
break;
}
}
adapter.notifyDataSetChanged();
}
else {
thisRowHolder.toggleButton.setBackgroundDrawable(//enabled button);
thisRowHolder.toggleButton.setChecked(true);
for (int i = 0; i < colorList.size(); i++) {
if (colorList.get(i) == (Integer)v.getTag()) {
colorList.get(i).setSomething(1);
break;
}
}
adapter.notifyDataSetChanged();
}
}
});
if (c.getSomething()>0) {
holder.toggleButton.setBackgroundDrawable(//enabled button);
holder.toggleButton.setChecked(true);
}
else {
holder.toggleButton.setBackgroundDrawable(//normal button);
holder.toggleButton.setChecked(false);
}
return rowView;
}
Question
What am I doing wrong? why are other buttons in third row toggling even though i'm toggling buttons in row one.
I read that this happens because the listView recycles, is there no way to fix it? Some strategies i've tried, to no avail, based on similar questions: 1) put onClickListener
in the if
clause. 2) instead of setting int
in setTag
instead set the holder
and use that holder
in onClickListener
update
I've updated all the code in the question with suggestions I received.