Android ListView的批量处理(多选/反选/删除)
在Android开发中经常遇到使用ListView的情况,有时候需要的不仅仅是列表显示,还有长按列表进行多选,并且批量删除的情况,在这里记录一下自己的所学。
先上效果图:

几个需要用到的核心方法:
//设置多选模式,下面的方法基于设置多选模式
list.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
//获取Item选择状态:
list.isItemChecked(i);
//设置Item选择状态
list.setItemChecked(i, true);
//清除全部选中状态
list.clearChoices();
简述原理
多选模式下,ListView在触发OnItemClick时会设置Item为true,再点一次为false,
我们只需创建一个isMultiplSelectionMode来传递判断当前为多选模式,
在全选时遍历list.setItemChecked()为true;
反选时遍历list.isItemChecked(i)为true的set为false,false则为true,
删除时直接遍历list.isItemChecked(i)为true的在适配器上直接remove删除即可
假装深入源码
我们知道ListView继承AbsListView,
通过查看他的源码的isItemChecked方法,可以看到
...
    public boolean isItemChecked(int position) {
        if (mChoiceMode != CHOICE_MODE_NONE && mCheckStates != null) {
            return mCheckStates.get(position);
        }
        return false;
    }
...
首先判断了当前选择模式不等于默认的单选模式 && mCheckStates 不为空的时候从这个mCheckStates去获取当前的item的选择状态,那我们再来看看这个mCheckStates到底是什么?
    /**
     * Running state of which positions are currently checked
     */
    SparseBooleanArray mCheckStates;
mCheckStates是SparseBooleanArray的实例,SparseBooleanArray实现了Cloneable接口,再往下就离题了,现在知道了mCheckStates本质是一个保存着Boolean的Array,并且这个Array与Items有关系,setItemChecked/isItemChecked都使用了mCheckStates,获取的就是Item的状态,逻辑他已经帮我们写好,我们只用用好isItemChecked即可。
(好像说了和没说一样,尴尬了|;)
直接上源码把
activity_main.xml
先界面:1个显示选择个数的TextView,3个Button,1个ListView
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
	xmlns:android="http://schemas.android.com/apk/res/android"
	android:layout_width="fill_parent"
	android:layout_height="fill_parent"
	android:orientation="vertical">
	<LinearLayout
        android:visibility="gone"
        android:id="@+id/ItemToolBar"
		android:orientation="horizontal"
		android:layout_width="wrap_content"
		android:layout_height="wrap_content">
		<TextView
			android:layout_width="wrap_content"
			android:layout_height="wrap_content"
			android:text="选择了0项"
			android:id="@+id/counttext"/>
		<Button
			android:layout_width="wrap_content"
			android:layout_height="wrap_content"
			android:text="全选"
			android:id="@+id/all"/>
		<Button
			android:layout_width="wrap_content"
			android:layout_height="wrap_content"
			android:text="反选"
			android:id="@+id/unall"/>
		<Button
			android:layout_width="wrap_content"
			android:layout_height="wrap_content"
			android:text="删除"
			android:id="@+id/del"/>
	</LinearLayout>
	<ListView
		android:layout_width="match_parent"
		android:layout_height="match_parent"
		android:id="@+id/mylistview"/>
</LinearLayout>
listview_item.xml
当然还有Item项的界面,简单点,两个TextView,一个标题,一个内容
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
	xmlns:android="http://schemas.android.com/apk/res/android"
	android:layout_width="fill_parent"
	android:layout_height="fill_parent"
	android:orientation="vertical">
	<TextView
		android:layout_width="wrap_content"
		android:layout_height="wrap_content"
		android:text="Large Text"
		android:textAppearance="?android:attr/textAppearanceLarge"
		android:id="@+id/lv_text1"/>
	<TextView
		android:layout_width="wrap_content"
		android:layout_height="wrap_content"
		android:text="Small Text"
		android:textAppearance="?android:attr/textAppearanceSmall"
		android:id="@+id/lv_text2"/>
</LinearLayout>
MyAdapter.java
ListView的适配器,重写了getView方法,让当前可视部分的项目状态为选中时改变背景颜色,关于geiView的ViewHolder部分可以看这的文章【Android开发中常用的ListView列表的优化方式ViewHolder】,简而言之就是一种列表优化方式。
public class MyAdapter extends BaseAdapter {
   public ArrayList<HashMap<String, Object>> balistItem = new ArrayList<HashMap<>>();
    @Override
    public int getCount() {
        return balistItem.size();
    }
    @Override
    public long getItemId(int p1) {
        return p1);
    }
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder viewHolder;
        if (convertView == null) {
            viewHolder = new ViewHolder();
            convertView = View.inflate(MainActivity.CONTEXT, R.layout.listview_item, null);
            viewHolder.title = convertView.findViewById(R.id.lv_text1);
            viewHolder.text = convertView.findViewById(R.id.lv_text2);
            convertView.setTag(viewHolder);
        } else {
            viewHolder = (ViewHolder)convertView.getTag();
        }
        viewHolder.title.setText(balistItem.get(position).get("标题").toString());
        viewHolder.text.setText(balistItem.get(position).get("内容").toString());
        //判断position位置是否被选中,改变颜色
        if (MainActivity.list.isItemChecked(position) && MainActivity.isMultipleSelectionMode) {
                convertView.setBackgroundColor(0xffff521d);
            } else {
                convertView.setBackgroundColor(0xff1E90FF);
        }
        return convertView;
    }
    public MyAdapter(List<? extends Map<String, ?>> data) {
        this.balistItem = (ArrayList<HashMap<String, Object>>) data;
    }    
    private static class ViewHolder {
        TextView title;
        TextView text;
        public static ViewHolder newsInstance(View convertView) {
            ViewHolder holder = (ViewHolder) convertView.getTag();
            if (holder == null) {
                holder = new ViewHolder();
                holder.title = convertView.findViewById(R.id.lv_text1);
                holder.text = convertView.findViewById(R.id.lv_text2);
                convertView.setTag(holder);
            }
            return holder;
        }
    }
}
MainActivity.java
创建数据,并添加至适配器,设置长按进入多选模式,
public class MainActivity extends AppCompatActivity {
    static ListView list;
    static MyAdapter listItemAdapter;//适配器
    static boolean isMultipleSelectionMode;//判断进入多选模式
    public static ArrayList<HashMap<String, Object>> AdapterList = new ArrayList<>();  //数据
    public static Context CONTEXT;
    TextView counttext;
    LinearLayout ItemToolBar;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        CONTEXT = this.getApplicationContext();
        //初始化数据
        initData();
         counttext = this.findViewById(R.id.counttext);//选中时更改的textview
         ItemToolBar = this.findViewById(R.id.ItemToolBar);//多选模式的工具栏
        list.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
        listItemAdapter = new MyAdapter(AdapterList); //新建并配置ArrayAapeter
        list.setAdapter(listItemAdapter);
        list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> p, View v, int index,
                                    long arg3) {
                if (isMultipleSelectionMode) {
                    setCountChange();             
                }
                listItemAdapter.notifyDataSetChanged();
            }
        });
        list.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
            @Override
            public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long itemId) {
                if (isMultipleSelectionMode) {
                    ItemToolBar.setVisibility(View.GONE);
                    isMultipleSelectionMode = false;
                    list.clearChoices();//取消选中状态
                    Toast.makeText(CONTEXT, "退出多选模式", Toast.LENGTH_LONG).show();
                } else {
ItemToolBar.setVisibility(View.VISABLE);                             isMultipleSelectionMode =true;
                    listItemAdapter.notifyDataSetChanged();
                    //多选模式
                    Toast.makeText(CONTEXT, "进入多选模式", Toast.LENGTH_LONG).show();
                    for(int i = 0;i < listItemAdapter.balistItem.size();i++){
                        Log.d("del","Item" + i + "的状态:" + list.isItemChecked(i));
                    }
                    return true;
                }
                listItemAdapter.notifyDataSetChanged();
                setCountChange();
                return false;
            }
        });
//设置按钮单机事件绑定
 setButtonClick();
    }
    public void setCountChange(){
        counttext.setText("选中了" + list.getCheckedItemCount() +"项");
    }
    public void initData(){
        list = this.findViewById(R.id.mylistview);
        for(int i = 0;i< 5;i++){
            HashMap<String,Object> map = new HashMap<>();
            map.put("标题","这是标题" + i);
            map.put("内容","这是内容" + i);
            AdapterList.add(map);
        }
    }
    public void setButtonClick(){
        Button all = this.findViewById(R.id.all);
        Button unall = this.findViewById(R.id.unall);
        Button del = this.findViewById(R.id.del);
        all.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
               for(int i = 0;i < listItemAdapter.balistItem.size();i++){
                  list.setItemChecked(i,true);
               }
                setCountChange();
            }
        });
        unall.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                for(int i = 0;i < listItemAdapter.balistItem.size();i++){
                    if(list.isItemChecked(i)){
                        list.setItemChecked(i,false);
                        list.setItemChecked(i,false);
                    }else {
                        list.setItemChecked(i,true);
                    }
                }
                setCountChange();
            }
        });
        del.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                for(int i = 0;i < listItemAdapter.balistItem.size();i++){
                    if(list.isItemChecked(i)){
                        listItemAdapter.balistItem.remove(i);
                        listItemAdapter.notifyDataSetChanged();
                    }
                }
                list.clearChoices();
                setCountChange();
            }
        });
    }
}
demo apk文件下载地址:https://files.cnblogs.com/files/zzerx/app-debug(1).apk
Android ListView的批量处理(多选/反选/删除)的更多相关文章
- Jquery 1.8全选反选删除选中项实现
		JQuery1.6以后,Prop的出现,让1.6以下的全选反选效果全部失效了.以下是修正后的版本: 全选反选效果: $(".checkbox").click(function () ... 
- Vue-表单验证-全选-反选-删除-批量删除
		<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ... 
- [整] Android ListView 去除边缘阴影、选中色、拖动背景色等
		以下是通过XML定义的方式实现,如果需要通过代码实现,找到对应是set方式设置即可. 去除ListView滑到顶部和底部时边缘的黑色阴影: android:fadingEdge="none& ... 
- php对表格进行批量操作如全选反选删除功能
		<!DOCTYPE> <html> <head> <meta http-equiv="content-type" content=&quo ... 
- android ListView内数据的动态添加与删除
		main.xml 文件: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns ... 
- Android ListView实现仿iPhone实现左滑删除按钮
		需要自定义ListView.这里就交FloatDelListView吧. 复写onTouchEvent方法.如下: @Override public boolean onTouchEvent(Moti ... 
- Android ListView批量选择(全选、反选、全不选)
		APP的开发中,会常遇到这样的需求:批量取消(删除)List中的数据.这就要求ListVIew支持批量选择.全选.单选等等功能,做一个比较强大的ListView批量选择功能是很有必要的,那如何做呢? ... 
- android UI进阶之实现listview中checkbox的多选与记录
		今天继续和大家分享涉及到listview的内容.在很多时候,我们会用到listview和checkbox配合来提供给用户一些选择操作.比如在一个 清单页面,我们需要记录用户勾选了哪些条目.这个的实现并 ... 
- 【转】android UI进阶之实现listview中checkbox的多选与记录--不错
		原文网址:http://www.cnblogs.com/notice520/archive/2012/02/17/2355415.html 今天继续和大家分享涉及到listview的内容.在很多时候, ... 
随机推荐
- CCF_ 201312-2_ISBN号码
			水. #include<cstdio>#include<string>#include<iostream>using namespace std; int main ... 
- lua学习之基础概念篇
			基础概念 程序块 (chunk) 定义 lua 中的每一个源代码文件或在交互模式(Cmd)中输入的一行代码都称之为程序块 一个程序块就是一连串语句或者命令 lua 中连续的语句不需要分隔符,但为了可读 ... 
- ARTS Week 6
			Dec 2, 2019 ~ Dec 8, 2019 Algorithm 从本周开始,由于要涉及某一算法,但我又有选择困难症.所以我决定在Leetcode刷题的,用ARTS中的算法部分来记录本周值得记录 ... 
- Python应用——多变量的灵活处理
			本文始发于个人公众号:TechFlow,原创不易,求个关注 我们都知道Python是一个非常灵活的语言,以至于如果它不是你的第一门语言,你会发现它总能给你各种各样的惊喜,让你忍不住惊叹:woc,还有这 ... 
- Go语言实现:【剑指offer】二叉树中和为某一值的路径
			该题目来源于牛客网<剑指offer>专题. 输入一颗二叉树的跟节点和一个整数,打印出二叉树中结点值的和为输入整数的所有路径.路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路 ... 
- JAVA中的约瑟夫环和猴子王问题
			今天在书上(书名< java程序设计经典300例 >李源编著)看了一个有趣的问题,那就是java版的约瑟夫问题,想必大一的小伙伴们早就用c写过了吧 今天我在复习一下 首先问题是这样的n个人 ... 
- The related functions and attributes for managing attributes - 操作属性的重要属性和函数
			特性 property 都是类属性(静态变量),但是特性管理的其实是实例属性的存取, ****** 回顾 -'类方法' classmethod 和 '静态方法' staticmethod 皆可以访问类 ... 
- [Effective Java 读书笔记] 第二章 创建和销毁对象 第一条
			第二章 创建和销毁对象 第一条 使用静态工厂方法替代构造器,原因: 静态工厂方法可以有不同的名字,也就是说,构造器只能通过参数的不同来区分不同的目的,静态工厂在名字上就能表达不同的目的 静态工厂方法 ... 
- 【机器学习】算法原理详细推导与实现(六):k-means算法
			[机器学习]算法原理详细推导与实现(六):k-means算法 之前几个章节都是介绍有监督学习,这个章解介绍无监督学习,这是一个被称为k-means的聚类算法,也叫做k均值聚类算法. 聚类算法 在讲监督 ... 
- ELK日志分析平台
			ELK日志分析平台 ELK(1): ELK-简介 ELK(2): ELK-安装环境和安装包 ELK(3): ELK-安装elasticsearch ELK(4): ELK-安装logstash ... 
