Reputation: 2172
i have a listview with checkbox on each row , when i select any checkbox and then scroll the screen , the checkboxes for each item changed ranomally , i mean the uncheck it becomse check and sometimes it stay uncheck , and then when i scroll up again , the checked one becomes uncheck , i found this question Android listview with checkbox problem , and the users says it helps them, but i can't understand what sholud i do , and help please
this is my adapter
class RestaurantAdapter extends BaseAdapter {
private static LayoutInflater inflater = null;
private ArrayList<HashMap<String, String>> data;
Activity activity;
public RestaurantAdapter(Activity activity,
ArrayList<HashMap<String, String>> data) {
// TODO Auto-generated constructor stub
this.activity = activity;
this.data = data;
inflater = (LayoutInflater) activity
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return data.size();
}
@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return position;
}
@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
View vi = convertView;
if (vi == null)
vi = inflater.inflate(R.layout.restaurant_multi_select_list_item,
null);
TextView name = (TextView) vi
.findViewById(R.id.restaurant_multi_select_title);
ImageView image = (ImageView) vi
.findViewById(R.id.restaurant_multi_select_list_item_image);
CheckBox cb = (CheckBox) vi
.findViewById(R.id.restaurant_multi_select_checkBox);
HashMap<String, String> restaurant = data.get(position);
name.setText(restaurant.get("name"));
image.setImageResource(Integer.parseInt(restaurant.get("image")));
return vi;
}
}
Upvotes: 5
Views: 2589
Reputation: 28799
It is about cycle and recycle the elements in the listview , take a look at converView
concept.
i edit your code and added a status array to keep saving the last value of each checkbox and load it in every cycle and recycle,
class RestaurantAdapter extends BaseAdapter {
private ArrayList<Boolean> status = new ArrayList<Boolean>();
private static LayoutInflater inflater = null;
private ArrayList<HashMap<String, String>> data;
Activity activity;
public RestaurantAdapter(Activity activity,
ArrayList<HashMap<String, String>> data) {
// TODO Auto-generated constructor stub
this.activity = activity;
this.data = data;
inflater = (LayoutInflater) activity
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
for (int i = 0; i < data.size(); i++) {
status.add(false);
}
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return data.size();
}
@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return position;
}
@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
View vi = convertView;
if (vi == null)
vi = inflater.inflate(R.layout.restaurant_multi_select_list_item,
null);
TextView name = (TextView) vi
.findViewById(R.id.restaurant_multi_select_title);
ImageView image = (ImageView) vi
.findViewById(R.id.restaurant_multi_select_list_item_image);
CheckBox cb = (CheckBox) vi
.findViewById(R.id.restaurant_multi_select_checkBox);
cb.setOnCheckedChangeListener(new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
if (isChecked) {
status.set(position, true);
} else {
status.set(position, false);
}
}
});
cb.setChecked(status.get(position));
HashMap<String, String> restaurant = data.get(position);
name.setText(restaurant.get("name"));
image.setImageResource(Integer.parseInt(restaurant.get("image")));
return vi;
}
}
not that you have to use setOnCheckedChangeListener
on the getview , not on the listview
Upvotes: 12
Reputation: 2411
You need to set your checkbox's state explicitly in getView()
, based on whether it should be checked for that particular row or not.
The Views that are created to represent ListView elements are typically recycled when scrolling for performance reasons (which is what you're doing in your code with convertView
), so any view properties that you don't re-set explicitly when you're reusing that View will simply retain whatever state they were in the last time that particular View instance was used.
Upvotes: 2