Hey guys, I have a listactivity that uses a custom row layout. The layout consists of 2 labels, a imageview and a Checkbox.
I'm trying to fire a listener when the Checkbox is checked. The listener I wrote works, but instead of firing for the individual row, it fires for every single row in the listactivity. Like if I check the checkbox in my first row, the dialog will open and work correctly, however the 2nd, 3rd and 4th rows will also "fire".
Here's the appropriate area of my code:
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
if (v == null) {
LayoutInflater vi = (LayoutInflater) getContext().getSystemService(
Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(R.layout.row, null);
}
final item o = items.get(position);
if (o != null) {
TextView tt = (TextView) v.findViewById(R.id.name);
TextView bt = (TextView) v.findViewById(R.id.game);
CheckBox cb = (CheckBox) v.findViewById(R.id.caught);
if (cb != null && o.getStatus()) {
cb.setChecked(true);
} else {
cb.setChecked(false);
}
if (tt != null) {
tt.setText(o.getName());
}
if (bt != null && o.getStatus()) {
bt.setText("Game: " + o.getGame());
}
cb.setOnCheckedChangeListener(new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
o.setStatus(isChecked);
if (isChecked) {
AlertDialog.Builder builder2 = new AlertDialog.Builder(
context);
builder2.setTitle("What game are we talkin gabout?");
builder2.setItems(Checklist.GAMES,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,
int item) {
Toast.makeText(context,
Checklist.GAMES[item],
Toast.LENGTH_SHORT).show();
o.setGame(Checklist.GAMES[item]);
o.setStatus(true);
me.notifyDataSetChanged();
}
});
builder2.show();
} else {
o.setGame("");
o.setStatus(false);
me.notifyDataSetChanged();
}
}
});
}
return v;
}
Is there a more appropriate place to create my listener for the checkbox?
I think it's not a good soloution to assing a new OnCheckedChangeListener each time a view is updated with values. It would be better setting a listener only one time to a view at the point where this new view gets inflatet. You can make o-Object available for the listener by putting it into cb's tag (setTag(..)). Note that the onCheckedChanged event also fires when you set CB's state by cb.setChecked().
for example:
CheckBox cb = null;
if (v == null) {
LayoutInflater vi = (LayoutInflater) getContext().getSystemService(
Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(R.layout.row, null);
cb = (CheckBox) v.findViewById(R.id.caught);
// set a listener
cb.setOnCheckedChangeListener(new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
item o = (item) buttonView.getTag();
// show your dialog
}
});
}
item o = items.get(position);
if (o != null) {
TextView tt = (TextView) v.findViewById(R.id.name);
TextView bt = (TextView) v.findViewById(R.id.game);
cb = (CheckBox) v.findViewById(R.id.caught);
cb.setTag(o);
// set checked state & text
// ...
}