ClaireG
ClaireG

Reputation: 1244

CheckBox in ListView multiple select

Good day to all.

I have a list view with checkboxes near each textview. When I check one checkbox and scroll down, random other checkboxes also get checked. I've read this post and a couple others here and they all say that the state of each checkbox needs to be saved in a boolean list at getView(). How would I go about doing that?

Thanks.

Edited for code:

This is the code of the adapter, containing also the getView() method.

public class MyCustomAdapter extends BaseAdapter
{
    public ArrayList<Error> list;
    private Context mContext;
    private LayoutInflater mInflator;

    public MyCustomAdapter(Context context, int textViewResourceId, ArrayList<Error> list)
    {
        this.list = list;
        this.mContext = context;
        mInflator = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    }

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

@Override
public Error getItem(int position) 
{
    return list.get(position);
}

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

@Override
public View getView(int position, View convertView, ViewGroup parent) 
{
    ViewHolder holder;

    if(convertView == null)
    {
        holder = new ViewHolder();

        convertView = mInflator.inflate(R.layout.listviewrow, null);

        holder.text = (TextView)convertView.findViewById(R.id.text);
        holder.checkbox = (CheckBox)convertView.findViewById(R.id.checkbox);

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

    final int pos = position;
    holder.text.setText(list.get(position).getDescription());
    holder.checkbox.setOnCheckedChangeListener(new OnCheckedChangeListener() 
    {

        @Override
        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) 
        {
            list.get(pos).setChecked(isChecked);
        }
    });

    return convertView;
}

static class ViewHolder
{
    TextView text;
    CheckBox checkbox;
}



}

Upvotes: 2

Views: 25617

Answers (4)

Saurabh Android
Saurabh Android

Reputation: 668

Below code working for me

My mainActivity

public class MainActivity extends Activity {

    private ListView llChb;

    private String[] data = { "a", "b", "c", "d", "e", "f", "g", "h", "i", "j",
            "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w",
            "x", "y", "z" };
    private ArrayList<String> arrData=null;

    private ArrayList<InfoRowdata> infodata;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        arrData=new ArrayList<String>();
        arrData.add("a");
        arrData.add("b");
        arrData.add("c");
        arrData.add("d");
        arrData.add("e");
        arrData.add("f");
        arrData.add("g");
        arrData.add("h");
        arrData.add("i");
        arrData.add("j");
        arrData.add("k");
        arrData.add("l");
        arrData.add("m");
        arrData.add("n");
        arrData.add("o");
        arrData.add("p");
        llChb = (ListView) findViewById(R.id.llChb);

        infodata = new ArrayList<InfoRowdata>();
        for (int i = 0; i < data.length; i++) {
            infodata.add(new InfoRowdata(false, i));
            // System.out.println(i);
            //System.out.println("Data is == "+data[i]);
        }
        llChb.invalidate();
        llChb.setAdapter(new MyAdapter());
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.activity_main, menu);
        return true;
    }

    public class MyAdapter extends BaseAdapter {

        @Override
        public int getCount() {
            // TODO Auto-generated method stub
            return data.length;
        }

        @Override
        public Object getItem(int position) {
            // TODO Auto-generated method stub
            return null;
        }

        @Override
        public long getItemId(int position) {
            // TODO Auto-generated method stub
            return 0;
        }

        @Override
        public View getView(final int position, View convertView, ViewGroup parent) {
            // TODO Auto-generated method stub
            View row = null;
            row = View.inflate(getApplicationContext(), R.layout.row, null);
            TextView tvContent=(TextView) row.findViewById(R.id.tvContent);
            //tvContent.setText(data[position]);
            tvContent.setText(data[position]);
            //System.out.println("The Text is here like.. == "+tvContent.getText().toString());

            final CheckBox cb = (CheckBox) row
                    .findViewById(R.id.chbContent);
            cb.setOnClickListener(new OnClickListener() {

                @Override
                public void onClick(View v) {
                    // TODO Auto-generated method stub
                    if (infodata.get(position).isclicked) {
                            infodata.get(position).isclicked = false;
                        } else {
                            infodata.get(position).isclicked = true;
                        }

                    for(int i=0;i<infodata.size();i++)
                    {
                        if (infodata.get(i).isclicked)
                        {
                            System.out.println("Selectes Are == "+ data[i]);
                        }
                    }
                }
            });

            if (infodata.get(position).isclicked) {

                cb.setChecked(true);
            }
            else {
                cb.setChecked(false);
            }
            return row;
        }

    }
}

My InfoRowdata Model Class

public class InfoRowdata {

    public boolean isclicked=false;
    public int index;
    /*public String fanId;
    public String strAmount;*/

    public InfoRowdata(boolean isclicked,int index/*,String fanId,String strAmount*/)
    {
        this.index=index;
        this.isclicked=isclicked;
        /*this.fanId=fanId;
        this.strAmount=strAmount;*/
    }

}

My MainXml

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity" >

    <ListView
        android:id="@+id/llChb"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >
    </ListView>

</RelativeLayout>

This is custom RowXml for ListView

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/rlMain"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" >

        <RelativeLayout
            android:id="@+id/rlInner"
            android:layout_width="fill_parent"
            android:layout_height="50dp" >

            <TextView
                android:id="@+id/tvContent"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerVertical="true"
                android:layout_marginLeft="20dp"
                android:text="Medium Text"
                android:textColor="#000000" />

            <CheckBox
                android:id="@+id/chbContent"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentRight="true"
                android:layout_centerVertical="true"
                android:layout_marginRight="10dp" />

        </RelativeLayout>

    </RelativeLayout>

Upvotes: 10

Shiva N
Shiva N

Reputation: 1

If still your looking for answer here it goes. Some are commented in stackoverflow that , if we are using Custom Adapter or Custom ListView then we have to remember checkbox status. But no need to remember. ListView will remember it. So before implementation please understand the below items.

  1. What is ListView and adapter.
  2. How adapter call getView and update each item in the listView.
  3. What will happen when we scroll up/down(where some items in listview will be hidden. i.e what getView will return.)
  4. Go through the ListView APIs.This is important.

Once you learn above mentioned points then answer is very simple. ListView will remember all the status and can be extracted using isItemChecked by passing position as parameter.

Upvotes: -1

selva_pollachi
selva_pollachi

Reputation: 4217

Use this

        ViewHolder holder;
        holder = new ViewHolder();

        convertView = mInflator.inflate(R.layout.listviewrow, null);

        holder.text = (TextView)convertView.findViewById(R.id.text);
        holder.checkbox = (CheckBox)convertView.findViewById(R.id.checkbox);

        convertView.setTag(holder);

Instead of

 ViewHolder holder;

    if(convertView == null)
    {
        holder = new ViewHolder();

        convertView = mInflator.inflate(R.layout.listviewrow, null);

        holder.text = (TextView)convertView.findViewById(R.id.text);
        holder.checkbox = (CheckBox)convertView.findViewById(R.id.checkbox);

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

I faced same problem. May be you will get answer !

Upvotes: 0

Zoubiock
Zoubiock

Reputation: 1165

View in listView are recycled, it means that when a view is going out of the screen, it is reused for the next view to appear. That's mean also, that if you don't set the checkbox to any state you want, it will keep the state from the recycled view.

What kind of adapter do you use ?

Upvotes: 3

Related Questions