Reputation: 3193
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
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
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
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
Reputation: 13501
Its happening because you have inflated a checkBox with same id multiple times. So modify your code in following way,
Add a TableRow/LinearLayout in Xml in the place of checkBox.
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.
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
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