• 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

  • 相关阅读:
    新概念英语第三册21-40课(转)
    多线程---线程通信
    多线程----线程同步
    多线程----线程创建的四种方式
    从0开始整合SSM框架-1.mybatis
    easyUI datagrid 动态绑定列名称
    java分享第五天(数组)
    java分享第四天(循环)
    java分享第三天(异常)
    java分享第二天(变量及命名规范)
  • 原文地址:https://www.cnblogs.com/zzerx/p/12355299.html
Copyright © 2020-2023  润新知