1

I am working on a application which shows listView with checkBoxes. When I scroll the listView the Value of CheckBoxes got Cleared.

Below is my code

adapter class:

public class Conference_listViewAdapter extends BaseAdapter {
    Activity context;
    LayoutInflater inflater;
    public static List<Model> data = null;
    ArrayList<String> id_list = new ArrayList<String>();
    ViewHolder holder;
    int pos;

    public Conference_listViewAdapter(Activity context,List<Model> list, ArrayList<String> id_list) {
        data = list;
        this.id_list = id_list;     
        this.context = context;
    }


    @Override
    public int getCount() {
        return data.size();
    }


    @Override
    public Object getItem(int position) {
        return data.get(position).getName();
    }

    @Override
    public long getItemId(int position) {
        return Long.valueOf(id_list.get(position));
    }

    public View getView(final int position, View convertView, ViewGroup parent) {

        View view = null;

        if (convertView == null) {
            LayoutInflater inflator = context.getLayoutInflater();
            view = inflator.inflate(R.layout.people_list_item1, null);
            holder = new ViewHolder();
            holder.title = (TextView) view.findViewById(R.id.tv_name);
            holder.image = (ImageView) view.findViewById(R.id.avtaar);
            holder.favorite = (CheckBox) view.findViewById(R.id.fav);
            holder.favorite.setTag(position);
            view.setTag(holder);

            holder.favorite.setTag(data.get(position));
        } else {
            view = convertView;
            ((ViewHolder) view.getTag()).favorite.setTag(data.get(position));
        }


        holder.favorite.setOnCheckedChangeListener(new OnCheckedChangeListener() {

            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {                    
                Model element = (Model) holder.favorite.getTag();
                element.setSelected(buttonView.isChecked());     
                //notifyDataSetChanged();
            }
        });


        ViewHolder holder = (ViewHolder) view.getTag();

        holder.favorite.setChecked(data.get(position).isSelected());
        holder.title.setText(data.get(position).getName());



        try {
            holder.image.setImageBitmap(openPhoto(Long.valueOf(id_list.get(position))));
        } catch (Exception e) {
            e.printStackTrace();
        }

        return view;
    }

    class ViewHolder {
        TextView title;
        TextView model;
        ImageView image;
        CheckBox favorite;
    }


}

data model class

public class Model {

    private String name;
    private boolean selected;

    public Model(String name) {
        this.name = name;
        selected = false;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public boolean isSelected() {
        return selected;
    }

    public void setSelected(boolean selected) {
        this.selected = selected;
    }

} 

Don't know where I am doing it wrong.

rene
  • 41,474
  • 78
  • 114
  • 152

4 Answers4

2

You have to save the state of the ViewHolder. Then set the tag when convertView == null and get it in the else condition.

Check the way I did:

public class Conference_listViewAdapter extends ArrayAdapter<Model> {
    Activity context;
    LayoutInflater inflater;
    public static List<Model> data = null;
    ArrayList<String> id_list = new ArrayList<String>();

    int pos;


    public Conference_listViewAdapter(Activity context, List<Model> list, ArrayList<String> id_list) {
        super(context, R.layout.people_list_item1, list);
        this.context = context;
        this.data = list;
        this.id_list = id_list; 
    }



    public View getView(final int position, View convertView, ViewGroup parent) {
        View view = null;       
        if (convertView == null) {
            LayoutInflater inflator = context.getLayoutInflater();
            view = inflator.inflate(R.layout.people_list_item1, null);
            final ViewHolder holder = new ViewHolder();
            holder.title = (TextView) view.findViewById(R.id.tv_name);
            holder.image = (ImageView) view.findViewById(R.id.avtaar);
            holder.favorite = (CheckBox) view.findViewById(R.id.fav);

            view.setTag(holder);

            holder.favorite.setTag(data.get(position));

            holder.favorite.setOnCheckedChangeListener(new OnCheckedChangeListener() {

                public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {                    
                    Model element = (Model) holder.favorite.getTag();
                    element.setSelected(buttonView.isChecked());     
                }
            });


        } else {
            view = convertView;
            ((ViewHolder) view.getTag()).favorite.setTag(data.get(position));
        }





        ViewHolder holder = (ViewHolder) view.getTag();     
        holder.favorite.setChecked(data.get(position).isSelected());
        holder.title.setText(data.get(position).getName());

        try {
            holder.image.setImageBitmap(openPhoto(Long.valueOf(id_list.get(position))));
        } catch (Exception e) {
            e.printStackTrace();
        }

        return view;
    }




    static class ViewHolder {
        protected TextView title;
        protected CheckBox favorite;
        ImageView image;
    }
Maveňツ
  • 1
  • 12
  • 50
  • 89
0

change this..

  @Override
public Object getItem(int position) {
    return position;
}

to..

  @Override
public Object getItem(int position) {
    return data.get(position);
}

Update:

try this..

public View getView(final int position, View convertView, ViewGroup parent) {

    View view = null;

    if (convertView == null) {
        LayoutInflater inflator = context.getLayoutInflater();
        view = inflator.inflate(R.layout.people_list_item1, null);
        holder = new ViewHolder();
        holder.title = (TextView) view.findViewById(R.id.tv_name);
        holder.image = (ImageView) view.findViewById(R.id.avtaar);
        holder.favorite = (CheckBox) view.findViewById(R.id.fav);
        holder.favorite.setOnCheckedChangeListener(new OnCheckedChangeListener() {

            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {                    
               //do what you want..   
            }
        });

        view.setTag(holder);
    } else {
       holder = (ViewHolder) view.getTag();
    }

    holder.favorite.setChecked(data.get(position).isSelected());
    holder.title.setText(data.get(position).getName());



    try {
        holder.image.setImageBitmap(openPhoto(Long.valueOf(id_list.get(position))));
    } catch (Exception e) {
        e.printStackTrace();
    }

    return view;
}
Sjd
  • 1,261
  • 1
  • 12
  • 11
0

In similar situations like listview with checkboxes,radiobuttons,count box etc I use to do as follows 1) keep an arraylist with a size similar to the listview(number of rows) 2) this array/arraylist will be initialized in the constructor of adapter class with all positions as zero 3) inside getView() after declaring checkbox and setting its tag as position

public class Conference_listViewAdapter extends BaseAdapter {
    Activity context;
    LayoutInflater inflater;
    public static List<Model> data = null;
    ArrayList<String> id_list = new ArrayList<String>();
     ArrayList<String> myarray=new java.util.ArrayList<String>();   
    ViewHolder holder;
    int pos;


    public Conference_listViewAdapter(Activity context,List<Model> list, ArrayList<String> id_list) {
        data = list;
        this.id_list = id_list;
        this.context = context;
for(int i=0;i<id_list.size();i++)
myarray.add("0");
    }


    @Override
    public int getCount() {
        return data.size();
    }


    @Override
    public Object getItem(int position) {
        return position;
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    public View getView(final int position, View convertView, ViewGroup parent) {

        View view = null;

        if (convertView == null) {
            LayoutInflater inflator = context.getLayoutInflater();
            view = inflator.inflate(R.layout.people_list_item1, null);
            holder = new ViewHolder();
            holder.title = (TextView) view.findViewById(R.id.tv_name);
            holder.image = (ImageView) view.findViewById(R.id.avtaar);
            holder.favorite = (CheckBox) view.findViewById(R.id.fav);
            holder.favorite.setTag(position);
            view.setTag(holder);

if(myarray.get(Integer.parseInt(holder.favorite.getTag().toString()).equalsIgnoreCase("1")
//make your checkbox checked
else
//keep checkbox unchecked
            holder.favorite.setOnCheckedChangeListener(new OnCheckedChangeListener() {

                public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {                    
   if(  isChecked)                   myarray.set(Integer.parseInt(holder.favorite.getTag().toString()),"1");    

else
myarray.set(Integer.parseInt(holder.favorite.getTag().toString()),"0"); 

notifydatasetchanged();
            });

            holder.favorite.setTag(data.get(position));
        } else {
            view = convertView;
            ((ViewHolder) view.getTag()).favorite.setTag(data.get(position));
        }


        ViewHolder holder = (ViewHolder) view.getTag();

        holder.favorite.setChecked(data.get(position).isSelected());
        holder.title.setText(data.get(position).getName());



        try {
            holder.image.setImageBitmap(openPhoto(Long.valueOf(id_list.get(position))));
        } catch (Exception e) {
            e.printStackTrace();
        }

        return view;
    }

    class ViewHolder {
        TextView title;
        TextView model;
        ImageView image;
        CheckBox favorite;
        Boolean selected;
    }   

}

always this saves my issues with listview scrolling..

Karthika PB
  • 1,373
  • 9
  • 16
0

This is a common error, I think. You need to set this code holder.favorite.setOnCheckedChangeListener(new OnCheckedChangeListener() outside the if/else block. The reason is whether convertView is = null or not, the listener should be set. I realize your code may need bit of arrangement but I think you could do that better than me since my code style is different. Is this clear enough though?

Another possible error is holder.favorite.setTag(position). The reason is code Model element = (Model) holder.favorite.getTag() in your listener. You're saving the int position and typecasting it to the Model class, could not work. Change the override getItem, first coding to do. Sample code in summary:

@Override
    public Object getItem(int position) {
        return data.get(position);   // return the Model
    }
...
holder.favorite.setTag( getItem(position) );

Note: Again holder.favorite.setTag should be set outside the if/else block. Only view.setTag(holder) could be set in the if block because it's a new view object.

Besides all this, I think your code design should work!

Suggested code changes...

public View getView(final int position, View convertView, ViewGroup parent) {

ViewHolder holder = null;    // different

if (convertView == null) {
   ...
   holder.favorite.setTag(data.get(position));    // different
   view.setTag(holder);                           // different

}
else {
   view = convertView;
   holder = (ViewHolder) view.getTag();    // different
}
...
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
   Model element = (Model) buttonView.getTag();    // different

Changes are:

  1. I use comments of different to emphasize code changes.
  2. ViewHolder holder is declared here in getView(). Remove the holder declaration on top inside the class. I think this is better coding style since holder is closer to find where you're using it, make it local to getView.
  3. The placement of holder.favorite.setTag and view.setTag is switched. I think this is a safer coding style. I think it is safer to set the holder first before using it as a parameter to object view. It may not matter, I admit.
  4. view.getTag is necessary when convertView is not = null. When you set the tag with view.getTag()).favorite.setTag in the same block, you're actually changing the content of the holder with unexpected behavior.
  5. In code (Model) buttonView.getTag(), buttonView is used instead of holder.favorite. I hope this gets the correct Model object.
The Original Android
  • 6,147
  • 3
  • 26
  • 31