使用自定义arrayadapter从listview android中删除复选框选择的多个项目

Posted

技术标签:

【中文标题】使用自定义arrayadapter从listview android中删除复选框选择的多个项目【英文标题】:Remove checkbox selected multiple items from listview android using custom arrayadapter 【发布时间】:2015-06-26 19:22:58 【问题描述】:

我有自定义 arrayadapter 用于显示列表视图的项目。我在 item_list.xml 文件中有两个文本视图和一个复选框。我想从列表视图中删除选中的项目。但问题是当检查多个项目然后没有从位置正确删除。下面是我的源代码。

    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;
        

【问题讨论】:

【参考方案1】:

按位置删除不是一个好的解决方法。 您应该尝试按对象删除。

这是示例代码

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;
    

编辑

如果您在删除时遇到出站异常,您可以尝试改用此循环

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

【讨论】:

我有新问题,当我向下滚动列表视图时,选中的项目复选框值未选中。它的原因是什么? @jack 在上面的答案中,您应该替换这行代码 - holder.chk.setChecked(ids.contains(position));使用以下行 -holder.chk.setChecked(ids.contains(items.get(position))); 当删除最后的记录,如 Chk 15 到 Chk 20 然后 arrayindexoutofbound 生成【参考方案2】:

我认为依赖于基于索引删除项目可能有点复杂,相反,最好依赖于删除项目本身。我对你的课做了一些修改。不确定它是否符合您的要求。

public class MainActivity extends Activity 
ListView listView;
Button btnDelete;
ArrayList<String> items = new ArrayList<String>();
ArrayList<String> selectedItems = 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 (selectedItems.size() > 0) 
                for (int i = 0; i < selectedItems.size(); i++) 
                    boolean isremoved = items.remove(selectedItems.get(i));
                    // items.remove(items.get(adapter.getItemViewType(ids.get(i))));
                    // items.remove(adapter.getItemViewType(ids.get(i)));
                    System.out.println();
                
                //selectedItems.clear();
                ((CustomAdapter) listView.getAdapter()).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.checkBox1);
            holder.txt = (TextView) convertView.findViewById(R.id.textView1);
            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(selectedItems.contains(items.get(position)));
        holder.chk.setOnCheckedChangeListener(new OnCheckedChangeListener() 
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) 
                if (isChecked) 
                    selectedItems.add(items.get(position));
                    System.out.println("IDS A: " + selectedItems.toString());
                 else 
                    if (selectedItems.contains(items.get(position))) 
                        int i = selectedItems.indexOf(items.get(position));
                        selectedItems.remove(i);
                        System.out.println("IDS R: " + selectedItems.toString());
                    
                
            
        );
        return convertView;
    


public class ViewHolder 
    CheckBox chk;
    TextView txt;
 

希望对你有帮助。

【讨论】:

我有新问题,当我向下滚动列表视图时,选中的项目复选框值未选中。它的原因是什么? @jack 你试过我发布的代码了吗?我认为即使您向下滚动,此代码也可以工作。 当我从列表视图中删除最后一项时,引发了 arrayindexoutofbound 异常。 @jack 你能发布你最新的代码吗,因为有了上面的代码,我可以毫无问题地删除最后一个项目。 让我们continue this discussion in chat.

以上是关于使用自定义arrayadapter从listview android中删除复选框选择的多个项目的主要内容,如果未能解决你的问题,请参考以下文章

Android中Spinner下拉列表(使用ArrayAdapter和自定义Adapter实现)

Android中Spinner下拉列表(使用ArrayAdapter和自定义Adapter实现) .

ListView:setItemChecked 仅适用于标准 ArrayAdapter - 在使用自定义 ArrayAdapter 时不起作用?

Android零基础入门第40节:自定义ArrayAdapter

如何使用 ArrayAdapter 为 ListView 编写自定义过滤器

ArrayAdapter使用自定义布局