I’ve created a custom ListView with checkboxes. I wanted to delete the selected items on “Delete” menu option selection.
I am handling the onCheckedChanged event on CheckBox. Here I maintain an ArrayList to note down the selected elements position. Now when the user selects the “Delete” menu item I do remove the choosen items from ListAdapter’s ArrayList.
Below is my code,
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
names = new ArrayList<String>();
names.add("first");
names.add("second");
names.add("three");
names.add("four");
names.add("five");
names.add("six");
names.add("seven");
names.add("eight");
names.add("nine");
listAdapter = new SelfAdapter(this,names);
this.setListAdapter(listAdapter);
}
@Override
public boolean onOptionsItemSelected(MenuItem menuItem){
int menuId = menuItem.getItemId();
ArrayList<Integer> selectedItems;
switch(menuId){
case R.id.delitem:
Log.d(TAG,"del item selected");
selectedItems = listAdapter.getSelected();
**//pick the selected position items and delete them from the
// listadapter arraylist**
for(Integer element: selectedItems){
Log.d(TAG,"Selected:"+element.toString());
names.remove(element.intValue());
listAdapter.notifyDataSetChanged();
}
}
return true;
}
Here is the code for custom adapter,
class SelfAdapter extends ArrayAdapter<String>{
ViewHolder holder = new ViewHolder();
private Activity context;
private ArrayList<String> names;
private String TAG = "SelfAdapter";
ArrayList<Integer> checkedPos; **//contains the selected items position**
public SelfAdapter(Context context, ArrayList names) {
super(context,R.layout.checkboxnlist, names);
this.context = (Activity) context;
this.names = names;
checkedPos = new ArrayList<Integer>();
}
@Override
public View getView(int position, View convertView, ViewGroup parent){
final int listPosition = position;
if(convertView == null){
LayoutInflater inflater = context.getLayoutInflater();
convertView = inflater.inflate(R.layout.checkboxnlist,parent,false);
holder.chkBox = (CheckBox)convertView.findViewById(R.id.chkvw);
holder.txtView = (TextView)convertView.findViewById(R.id.txtvw);
convertView.setTag(holder);
}
else{
holder = (ViewHolder) convertView.getTag();
}
holder.txtView.setText(names.get(position));
holder.chkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener(){
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
Log.d(TAG,"listPosition:"+listPosition);
if(isChecked){
checkedPos.add(new Integer(listPosition));
}
else{
checkedPos.remove(listPosition);
}
}
});
return convertView;
}
public ArrayList<Integer> getSelected(){
return checkedPos;
}
static class ViewHolder{
TextView txtView;
CheckBox chkBox;
}
}
Now the problem is that if select 1st,2nd items (for example) then I see the wrong items get deleted and the listview populate after this is completely wrong. Later if I attempt to delete the items it’s throwing “Index out of bounds exception”. I guess the code is going wrong in getView method.
Can some one help me in finding out what am doing wrong here.
Thanks
When you remove elements from
names, you also need to remove elements from thecheckedPosarray. Otherwise, the two arrays will have different lengths. Then when you try again,checkedPoswill be longer thannamesand you end up with the index out of bounds exception.Also, when you are deleting from
names, you can’t use a normal iterator through . If you are supposed to delete names at indexes 1 and 2, then when you delete name 1, name 2 moves up to position 1. But your indexing isn’t updated accordingly. The easiest solution is to iterate backwards through the position array, deleting from the end ofnamesbefore deleting from the beginning.P.S. It’s a little weird to switch from ordinal numbers (“first”, “second”) to cardinal numbers (“three”, “four”, etc.) in the middle of the list.