user user
user user

Reputation: 2172

android listview , the checkbox change random

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

Answers (2)

William Kinaan
William Kinaan

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

Cloudy
Cloudy

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

Related Questions