Search code examples
androidcheckboxandroid-listviewandroid-arrayadapter

Remove checkbox selected multiple items from listview android using custom arrayadapter


I have custom arrayadapter for displaying items for listview. I have two textview and one checkbox in item_list.xml file. I want to delete checked items from listview. But problem is when checked multiple items then not properly deleted from position. Below is my source code.

    public class MainActivity extends Activity {

     ListView listView;
        Button btnDelete;
        ArrayList<String> items = new ArrayList<String>();
        ArrayList<String> ids = new ArrayList<String>();
        CustomAdapter adapter;

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);

            listView = (ListView) findViewById(R.id.listView1);
            btnDelete = (Button) findViewById(R.id.btnDelete);

            for (int i = 0; i < 20; i++) {
                items.add("Chk " + i);
            }

            adapter = new CustomAdapter(MainActivity.this, R.layout.custome_list,
                    items);
            listView.setAdapter(adapter);

            btnDelete.setOnClickListener(new OnClickListener() {

                @Override
                public void onClick(View v) {

                    if (ids.size() > 0) {
                        for (int i = 0; i < ids.size(); i++) {
                            items.remove(ids.get(i));
//                        items.remove(items.get(adapter.getItemViewType(ids.get(i))));
//                        items.remove(adapter.getItemViewType(ids.get(i)));
                        }

                        adapter.notifyDataSetChanged();
                    }
                }
            });
        }

        public class CustomAdapter extends ArrayAdapter<String> {

            List<String> items;
            int resource;

            public CustomAdapter(Context context, int resource, List<String> items) {
                super(context, resource, items);
                this.items = items;
                this.resource = resource;
            }

            @Override
            public View getView(final int position, View convertView, ViewGroup parent) {
                final int pos = position;

                ViewHolder holder = null;

                if (convertView == null) {
                    holder = new ViewHolder();
                    LayoutInflater inflater = getLayoutInflater();

                    convertView = inflater.inflate(resource, null);

                    holder.chk = (CheckBox) convertView.findViewById(R.id.chk);
                    holder.txt = (TextView) convertView.findViewById(R.id.txt);
                    convertView.setTag(holder);
                } else {
                    holder = (ViewHolder) convertView.getTag();
                }

                holder.txt.setText(items.get(position));

                // you have to reload the check states
                holder.chk.setOnCheckedChangeListener(null);
                holder.chk.setChecked(ids.contains(items.get(position)));

                holder.chk
                        .setOnCheckedChangeListener(new OnCheckedChangeListener() {

                            @Override
                            public void onCheckedChanged(CompoundButton buttonView,
                                    boolean isChecked) {

                                if (isChecked) {
                                    ids.add(items.get(position));
                                    System.out.println("IDS A: " + ids.toString());
                                } else {
                                    if (ids.contains(items.get(position))) {
                                        //int i = ids.indexOf(position);
                                        ids.remove(items.get(position));
                                        System.out.println("IDS R: "
                                                + ids.toString());
                                    }
                                }

                            }
                        });
                return convertView;
            }
        }

        public class ViewHolder {
            CheckBox chk;
            TextView txt;
        }
}

Solution

  • Remove by position is not a good work around. You should try removing by the object instead.

    Here is the sample code

    public class MainActivity extends Activity {
    
        ListView listView;
        Button btnDelete;
        ArrayList<String> items = new ArrayList<String>();
        ArrayList<String> ids = new ArrayList<String>();
        CustomAdapter adapter;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            listView = (ListView) findViewById(R.id.listView1);
            btnDelete = (Button) findViewById(R.id.btnDelete);
    
            for (int i = 0; i < 20; i++) {
                items.add("Chk " + i);
            }
    
            adapter = new CustomAdapter(MainActivity.this, R.layout.custome_list,
                    items);
            listView.setAdapter(adapter);
    
            btnDelete.setOnClickListener(new OnClickListener() {
    
                @Override
                public void onClick(View v) {
    
                    if (ids.size() > 0) {
                        for (int i = 0; i < ids.size(); i++) {
                            items.remove(ids.get(i));
    //                      items.remove(items.get(adapter.getItemViewType(ids.get(i))));
    //                      items.remove(adapter.getItemViewType(ids.get(i)));
                        }
    
                        adapter.notifyDataSetChanged();
                    }
                }
            });
        }
    
        public class CustomAdapter extends ArrayAdapter<String> {
    
            List<String> items;
            int resource;
    
            public CustomAdapter(Context context, int resource, List<String> items) {
                super(context, resource, items);
                this.items = items;
                this.resource = resource;
            }
    
            @Override
            public View getView(final int position, View convertView, ViewGroup parent) {
                final int pos = position;
    
                ViewHolder holder = null;
    
                if (convertView == null) {
                    holder = new ViewHolder();
                    LayoutInflater inflater = getLayoutInflater();
    
                    convertView = inflater.inflate(resource, null);
    
                    holder.chk = (CheckBox) convertView.findViewById(R.id.chk);
                    holder.txt = (TextView) convertView.findViewById(R.id.txt);
                    convertView.setTag(holder);
                } else {
                    holder = (ViewHolder) convertView.getTag();
                }
    
                holder.txt.setText(items.get(position));
    
                // you have to reload the check states
                holder.chk.setOnCheckedChangeListener(null);
                holder.chk.setChecked(ids.contains(position));
    
                holder.chk
                        .setOnCheckedChangeListener(new OnCheckedChangeListener() {
    
                            @Override
                            public void onCheckedChanged(CompoundButton buttonView,
                                    boolean isChecked) {
    
                                if (isChecked) {
                                    ids.add(items.get(position));
                                    System.out.println("IDS A: " + ids.toString());
                                } else {
                                    if (ids.contains(items.get(position))) {
                                        //int i = ids.indexOf(position);
                                        ids.remove(items.get(position));
                                        System.out.println("IDS R: "
                                                + ids.toString());
                                    }
                                }
    
                            }
                        });
                return convertView;
            }
        }
    
        public class ViewHolder {
            CheckBox chk;
            TextView txt;
        }
    }
    

    Edit

    If you are getting outofbound exeption on deletion you can try using this loop instead

     for (String item : ids) {
             items.remove(item);
         }