Richa
Richa

Reputation: 3193

Custom listView multiselection

I am developing Listview where Multiple selection is possible,now the problem is when i scroll down or up the selection of items get lost and selection made on any other item except the selected one.

Below is my Activity.

  public class ContactPickerActivity extends Activity {

    private ArrayList<Contact> arr = new ArrayList<Contact>();
    private Context context;
    private ListView list;
    private ContactArrayAdapter adapter;
    private String strName,strNumber;
    private View view;  
    public static ArrayList<Boolean> arrBoolean = new ArrayList<Boolean>();

    @Override
    public void onCreate(Bundle savedInstance) {
        super.onCreate(savedInstance);
        setContentView(R.layout.contact_picker);
        ProgressDialog pd  = new ProgressDialog(this);
        list = (ListView)findViewById(R.id.contactList);
        arr = new ArrayList<Contact>();
        context = ContactPickerActivity.this;
        arr =  displayContacts();
        Log.i("ContactPicker", "Completed Displaying Contact list ::: " + arr.size());
        adapter = new ContactArrayAdapter(this,arr);
        list.setAdapter(adapter);
//              list.setAdapter(new ArrayAdapter<String>(this,
//                      android.R.layout.simple_list_item_multiple_choice, listContent));
        list.setOnItemClickListener(ContactSelectedListener);
        Log.i("Boolaean >>> ", arrBoolean.size() + "");


    }

    private OnItemClickListener ContactSelectedListener = new OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parent, View arg1, int arg2,long arg3) {
            Log.i("ListViewTest","Item Click");
            SparseBooleanArray checked = list.getCheckedItemPositions();
            for (int i = 0; i < arr.size(); i++) {
                Log.i("ListViewTest", arr.get(i)+ ": " + checked.get(i));
            }
        }
    };

    private ArrayList<Contact> displayContacts() {

        ContentResolver cr = getContentResolver();
        Cursor cur = cr.query(ContactsContract.Contacts.CONTENT_URI,null, null, null, null);
        Contact contact;
        if (cur.getCount() > 0) {
            while (cur.moveToNext()) {
                contact = new Contact();
                String id = cur.getString(cur.getColumnIndex(People._ID));
                String name = cur.getString(cur.getColumnIndex(People.DISPLAY_NAME));
                contact.setName(name);
                arr.add(contact);
            }
        }
        return arr;
    }
}
********* Adapter *****

public class ContactArrayAdapter extends BaseAdapter {

//  private final List<Contact> list;
    private Context context;    

    private LayoutInflater mInflater;
    private List<Contact> list; 

     public ContactArrayAdapter(Context context,ArrayList<Contact> arrPublicData) {

        this.mInflater = LayoutInflater.from(context);
        this.list = arrPublicData;
    }

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

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

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

    public View getView(int position, View convertView, ViewGroup parent) {
        View view = convertView;
        final ViewHolder viewHolder;
        if (view == null) {         
            view = mInflater.inflate(R.layout.multiselect_row, null);
            viewHolder = new ViewHolder();
            viewHolder.text = (TextView) view.findViewById(R.id.txtItem);
            viewHolder.checkbox = (CheckBox) view.findViewById(R.id.chkItem);

            viewHolder.checkbox
            .setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
                @Override
                public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {

                    Contact element = (Contact) viewHolder.checkbox.getTag();
                    element.setSelected(buttonView.isChecked());
                    ContactPickerActivity.arrBoolean.add(buttonView.isChecked());
                    Log.i("Boolaean 123 >>> ", buttonView.isChecked() + "");
                }
            });
            view.setTag(viewHolder);
            viewHolder.checkbox.setTag(list.get(position));
        } else {
            viewHolder = (ViewHolder) view.getTag();
            ((ViewHolder) view.getTag()).checkbox.setTag(list.get(position));
        }
        ViewHolder holder = (ViewHolder) view.getTag();
        holder.text.setText(list.get(position).getName());
        holder.checkbox.setChecked(list.get(position).isSelected());        
        return view;
    }

    static class ViewHolder {
    protected TextView text;
    protected CheckBox checkbox;
}

i m not able to get Items checked.... Any Help is appericiated...Thanx in Advance

Upvotes: 0

Views: 4150

Answers (5)

jeet
jeet

Reputation: 29199

Problem is in your getView method, please correct this as follows:

    public class ContactPickerActivity extends Activity {

    private ArrayList<Contacts> arr = new ArrayList<Contacts>();
    private Context context;
    private ListView list;
    private ContactArrayAdapter adapter;
    private String strName,strNumber;
    private View view;  
    public static boolean[] arrBoolean = null;

    @Override
    public void onCreate(Bundle savedInstance) {
        super.onCreate(savedInstance);
        //setContentView(R.layout.contact_picker);
        ProgressDialog pd  = new ProgressDialog(this);
        list = (ListView)findViewById(R.id.contactList);
        arr = new ArrayList<Contact>();
        context = ContactPickerActivity.this;
        arr =  displayContacts();
        arrBoolean=new boolean[arr.size()];
        Arrays.fill(arrBoolean, false);
        Log.i("ContactPicker", "Completed Displaying Contact list ::: " + arr.size());
        adapter = new ContactArrayAdapter(this,arr);
        list.setAdapter(adapter);
//              list.setAdapter(new ArrayAdapter<String>(this,
//                      android.R.layout.simple_list_item_multiple_choice, listContent));
        list.setOnItemClickListener(ContactSelectedListener);
        Log.i("Boolaean >>> ", arrBoolean.size() + "");


    }

    private OnItemClickListener ContactSelectedListener = new OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parent, View arg1, int position,long arg3) {
            Log.i("ListViewTest","Item Click");
            arrBoolean[position]=!arrBoolean[position];
            adapter.notifyDataSetChanged();
        }
    };

    private ArrayList<Contacts> displayContacts() {

        ContentResolver cr = getContentResolver();
        Cursor cur = cr.query(ContactsContract.Contacts.CONTENT_URI,null, null, null, null);
        Contacts contact;
        if (cur.getCount() > 0) {
            while (cur.moveToNext()) {
                contact = new Contacts();
                String id = cur.getString(cur.getColumnIndex(People._ID));
                String name = cur.getString(cur.getColumnIndex(People.DISPLAY_NAME));
                contact.setName(name);
                arr.add(contact);
            }
        }
        return arr;
    }
}
//********* Adapter *****

public class ContactArrayAdapter extends BaseAdapter {

//  private final List<Contact> list;
    private Context context;    

    private LayoutInflater mInflater;
    private List<Contacts> list; 

     public ContactArrayAdapter(Context context,ArrayList<Contact> arrPublicData) {

        this.mInflater = LayoutInflater.from(context);
        this.list = arrPublicData;
    }

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

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

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

    public View getView(int position, View convertView, ViewGroup parent) {
        View view = convertView;
        final ViewHolder viewHolder;
        if (view == null) {         
            view = mInflater.inflate(R.layout.multiselect_row, null);
            viewHolder = new ViewHolder();
            viewHolder.text = (TextView) view.findViewById(R.id.txtItem);
            viewHolder.checkbox = (CheckBox) view.findViewById(R.id.chkItem);


            view.setTag(viewHolder);
        } else {
            viewHolder = (ViewHolder) view.getTag();
        }
        ViewHolder holder = (ViewHolder) view.getTag();
        holder.text.setText(list.get(position).getName());
        holder.checkbox.setChecked(ContactPickerActivity.arrBoolean[position]);        
        return view;
    }

    static class ViewHolder {
    protected TextView text;
    protected CheckBox checkbox;
}

Upvotes: 1

jeet
jeet

Reputation: 29199

I have created a sample program, in which I am setting background color of the view according to state of the row, just change changing backgrouund code to check state;

public class SampleActivity extends Activity {
    private String[] arrItems={"A", "B", "C", "D", "E"};
    private boolean[] arrState={false, false, false, false, false};
    private ListView lv;
    private ArrAdapter adapter;
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        lv=(ListView) findViewById(R.id.lvTest);
        adapter=new ArrAdapter(this);
        lv.setAdapter(adapter);
        lv.setOnItemClickListener(new OnItemClickListener() {

            @Override
            public void onItemClick(AdapterView<?> adapterView, View view, int position,
                    long id) {
                // TODO Auto-generated method stub
                arrState[position]=!arrState[position];
                adapter.notifyDataSetChanged();
            }
        });

    }

    private class ArrAdapter extends ArrayAdapter<String>
    {
        Context mContext=null;
        public ArrAdapter(Context context) {
            super(context, R.layout.row);
            // TODO Auto-generated constructor stub
            mContext=context;
        }

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

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            // TODO Auto-generated method stub
            View vi=convertView;
            ViewHolder holder=null;
            if(vi==null)
            {
                vi=LayoutInflater.from(mContext).inflate(R.layout.row, parent, false);
                holder=new ViewHolder();
                holder.mTxt=(TextView) vi.findViewById(R.id.text1);
                vi.setTag(holder);
            }
            else
                holder=(ViewHolder) vi.getTag();
            holder.mTxt.setText(arrItems[position]);
            if(arrState[position])
                vi.setBackgroundColor(Color.BLUE);
            else
                vi.setBackgroundColor(Color.WHITE);
            return super.getView(position, convertView, parent);
        }


        private class ViewHolder
        {
            TextView mTxt=null;
        }


    }

    private void clear()
    {
        Arrays.fill(arrState, false);
        adapter.notifyDataSetChanged();
    }
}

Upvotes: 0

Roshan Jha
Roshan Jha

Reputation: 2091

public class ListAdapter extends BaseAdapter{

private LayoutInflater mInflater;
private ArrayList<String> arrPublicData;    
private int checkCount = 0;
private ArrayList<Boolean> check = new ArrayList<Boolean>();

 public ListAdapter(Context context,ArrayList<String> arrPublicData) {

    this.mInflater = LayoutInflater.from(context);
    this.arrPublicData = arrPublicData;
    checkCount = arrPublicData == null ? 0 : arrPublicData.size();
}

public int getCount() {
    return arrPublicData.size();
}

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

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

public View getView(int position, View convertView, ViewGroup parent) {
    final ViewHolder holder;
    View rowView = convertView;

    if (rowView == null) {
        rowView = mInflater.inflate(R.layout.multiselect_row, null);
        holder = new ViewHolder();

        holder.txtField = (TextView) rowView.findViewById(R.id.txtItem);
        holder.chkField = (CheckBox) rowView.findViewById(R.id.chkItem);
        holder.chkField.setOnCheckedChangeListener(checkedChangeListener);
        holder.chkField.setChecked(true);
        holder.chkField.setTag(R.id.chkItem, position);
        check.add(position, true);      
        rowView.setTag(holder);

    } else {
        holder = (ViewHolder) rowView.getTag();
    }

    holder.txtField.setText(arrPublicData.get(position));    
    if(check.get(position) == true)
    {
       holder.chkField.setText(arrPublicData.get(position));    
    }
    else
    {
       holder.chkField.setText(arrPublicData.get(position));    
    }       

    return rowView;
}

class ViewHolder { TextView txtField; CheckBox chkField; }

I think you are not checking condition whether checkbox is checked or not so your checkbox get change when you scroll your listview hope that will help

Upvotes: 2

ngesh
ngesh

Reputation: 13501

Its happening because you have inflated a checkBox with same id multiple times. So modify your code in following way,

  1. Add a TableRow/LinearLayout in Xml in the place of checkBox.

  2. in the getView method create a CheckBox at run time and set its ID as the position (list position) and add it to the TableRow/LinearLayout in xml using addView() method.

  3. now if the problem still persists, In CheckChanged Listener create Vector and add the position of checked items in the vector and while creating checkBox have a check on the Vector if the current view position is checked then use setChecked(true) method to check it.

may be i'm not clear but i don't know a better way to explain it.

Upvotes: 0

Sandip Jadhav
Sandip Jadhav

Reputation: 7155

http://www.marvinlabs.com/2010/10/custom-listview-ability-check-items/

check this

Edited

holder.chkField.setChecked(true);
holder.chkField.setTag(R.id.chkItem, position);
check.add(position, true);   

You need to change this as

if(check.getAt(position)){ 
   holder.chkField.setChecked(true);
}else{
   holder.chkField.setChecked(false);
}
holder.chkField.setTag(R.id.chkItem, position);

Put below line in Check listener on checked condition put true or false

check.add(position, isChecked);          

Upvotes: 5

Related Questions