在Android某些开发需求当中,有时候需要在listveiw中加入checkbox实现单选,多选操作。表面上看上去只是改变checkbox那么简单,然而实际开发中,实现起来并不是那么得心应手。尤其当listview比较多(比如屏幕最多只能显示10个item,但总共有12个item,也就是说listview的item数大于屏幕能够显示的item数)滑动屏幕的时候,由于适配器中getview()会重复使用被移除屏幕的item,所以会造成checkbox选择状态不正常的现象。自己在开发中碰到这样的问题很是苦恼,查了下资料,发现网上很少没有针对这类批量操作并没有一个完整的例子。搜了很多篇帖子才完美的实现这一常用的操作。所以在这里把这个Demo贴出来,供大家参考,希望能对大家有所帮助。

主界面的布局main.xml    这个就不多说什么

[html] view
plain
copy

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:layout_width="fill_parent"
  4. android:layout_height="wrap_content"
  5. android:orientation="vertical" >
  6. <LinearLayout
  7. android:orientation="vertical"
  8. android:layout_width="fill_parent"
  9. android:layout_height="wrap_content"
  10. >
  11. <TextView
  12. android:id="@+id/tv"
  13. android:layout_width="fill_parent"
  14. android:layout_height="50dip"
  15. android:textColor="#FCFCFC"
  16. android:textSize="11pt"
  17. android:gravity="center_vertical"
  18. android:layout_marginLeft="10dip"
  19. />
  20. <ListView
  21. android:id="@+id/lv"
  22. android:layout_width="fill_parent"
  23. android:layout_height="381dip"
  24. android:cacheColorHint ="#00000000"
  25. ></ListView>
  26. </LinearLayout>
  27. <RelativeLayout
  28. android:layout_width="fill_parent"
  29. android:layout_height="53dip"
  30. android:orientation="horizontal"
  31. >
  32. <Button
  33. android:id="@+id/selectall"
  34. android:layout_width="80dip"
  35. android:layout_height="50dip"
  36. android:layout_marginLeft="20dip"
  37. android:text="全选"
  38. android:gravity="center"
  39. />
  40. <Button
  41. android:id="@+id/inverseselect"
  42. android:layout_width="80dip"
  43. android:layout_height="50dip"
  44. android:layout_marginLeft="118dip"
  45. android:text="反选"
  46. android:gravity="center"
  47. />
  48. <Button
  49. android:id="@+id/cancel"
  50. android:layout_width="80dip"
  51. android:layout_height="50dip"
  52. android:layout_marginLeft="213dip"
  53. android:text="取消已选"
  54. android:gravity="center"
  55. />
  56. </RelativeLayout>
  57. </LinearLayout>

ListView每个item的布局,listviewitem.xml





这里需要注意的是,由于checkbox的点击事件优先级比listview的高,所以要添加Android:focusable="false"属性,使得checkbox初始的时候没有获取焦点。

另外这里是点击ListView的item控制checkbox的状态改变,也就是让item接收clik事件,所以需要加上android:focusableInTouchMode="false"这一属性。

[html] view
plain
copy

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <RelativeLayout  xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:layout_width="fill_parent"
  4. android:layout_height="55dip"
  5. android:orientation="horizontal"
  6. android:layout_marginTop="20dip"
  7. >
  8. <TextView
  9. android:id="@+id/item_tv"
  10. android:layout_width="267dip"
  11. android:layout_height="40dip"
  12. android:textSize="10pt"
  13. android:gravity="center_vertical"
  14. android:layout_marginLeft="10dip"
  15. />
  16. <CheckBox
  17. android:id="@+id/item_cb"
  18. android:layout_width="wrap_content"
  19. android:layout_height="wrap_content"
  20. android:focusable="false"
  21. android:focusableInTouchMode="false"
  22. android:clickable="false"
  23. android:layout_toRightOf="@id/item_tv"
  24. android:layout_alignParentTop="true"
  25. android:layout_marginRight="5dip"
  26. />
  27. </RelativeLayout >

ViewHolder类

[java] view
plain
copy

  1. package simtice.test.listview.viewholder;
  2. import Android.widget.CheckBox;
  3. import android.widget.TextView;
  4. public class ViewHolder {
  5. public TextView tv = null;
  6. public CheckBox cb = null;
  7. }

为listview自定义适配器,该类为主Activity类MainActivity.java的内部类

[java] view
plain
copy

  1. public static class MyAdapter extends BaseAdapter {
  2. public static HashMap<Integer, Boolean> isSelected;
  3. private Context context = null;
  4. private LayoutInflater inflater = null;
  5. private List<HashMap<String, Object>> list = null;
  6. private String keyString[] = null;
  7. private String itemString = null; // 记录每个item中textview的值
  8. private int idValue[] = null;// id值
  9. public MyAdapter(Context context, List<HashMap<String, Object>> list,
  10. int resource, String[] from, int[] to) {
  11. this.context = context;
  12. this.list = list;
  13. keyString = new String[from.length];
  14. idValue = new int[to.length];
  15. System.arraycopy(from, 0, keyString, 0, from.length);
  16. System.arraycopy(to, 0, idValue, 0, to.length);
  17. inflater = LayoutInflater.from(context);
  18. init();
  19. }
  20. // 初始化 设置所有checkbox都为未选择
  21. public void init() {
  22. isSelected = new HashMap<Integer, Boolean>();
  23. for (int i = 0; i < list.size(); i++) {
  24. isSelected.put(i, false);
  25. }
  26. }
  27. @Override
  28. public int getCount() {
  29. return list.size();
  30. }
  31. @Override
  32. public Object getItem(int arg0) {
  33. return list.get(arg0);
  34. }
  35. @Override
  36. public long getItemId(int arg0) {
  37. return 0;
  38. }
  39. @Override
  40. public View getView(int position, View view, ViewGroup arg2) {
  41. ViewHolder holder = new ViewHolder();
  42. if (view == null) {
  43. view = inflater.inflate(R.layout.listviewitem, null);
  44. }
  45. holder.tv = (TextView) view.findViewById(R.id.item_tv);
  46. holder.cb = (CheckBox) view.findViewById(R.id.item_cb);
  47. view.setTag(holder);
  48. }
  49. HashMap<String, Object> map = list.get(position);
  50. if (map != null) {
  51. itemString = (String) map.get(keyString[0]);
  52. holder.tv.setText(itemString);
  53. }
  54. holder.cb.setChecked(isSelected.get(position));
  55. return view;
  56. }
  57. }

最后,最重要的就是MainActivity.java中一些事件响应的处理

[java] view
plain
copy

  1. public class MainActivity extends Activity {
  2. TextView tv = null;
  3. ListView lv = null;
  4. Button btn_selectAll = null;
  5. Button btn_inverseSelect = null;
  6. Button btn_calcel = null;
  7. String name[] = { "G1", "G2", "G3", "G4", "G5", "G6", "G7", "G8", "G9",
  8. "G10", "G11", "G12", "G13", "G14" };
  9. ArrayList<String> listStr = null;
  10. private List<HashMap<String, Object>> list = null;
  11. private MyAdapter adapter;
  12. @Override
  13. public void onCreate(Bundle savedInstanceState) {
  14. super.onCreate(savedInstanceState);
  15. setContentView(R.layout.main);
  16. tv = (TextView) this.findViewById(R.id.tv);
  17. lv = (ListView) this.findViewById(R.id.lv);
  18. btn_selectAll = (Button) this.findViewById(R.id.selectall);
  19. btn_inverseSelect = (Button) this.findViewById(R.id.inverseselect);
  20. btn_calcel = (Button) this.findViewById(R.id.cancel);
  21. showCheckBoxListView();
  22. //全选
  23. btn_selectAll.setOnClickListener(new OnClickListener(){
  24. @Override
  25. public void onClick(View arg0) {
  26. listStr = new ArrayList<String>();
  27. for(int i=0;i<list.size();i++){
  28. MyAdapter.isSelected.put(i,true);
  29. listStr.add(name[i]);
  30. }
  31. adapter.notifyDataSetChanged();//注意这一句必须加上,否则checkbox无法正常更新状态
  32. tv.setText("已选中"+listStr.size()+"项");
  33. }
  34. });
  35. //反选
  36. btn_inverseSelect.setOnClickListener(new OnClickListener(){
  37. @Override
  38. public void onClick(View v) {
  39. for(int i=0;i<list.size();i++){
  40. if(MyAdapter.isSelected.get(i)==false){
  41. MyAdapter.isSelected.put(i, true);
  42. listStr.add(name[i]);
  43. }
  44. else{
  45. MyAdapter.isSelected.put(i, false);
  46. listStr.remove(name[i]);
  47. }
  48. }
  49. adapter.notifyDataSetChanged();
  50. tv.setText("已选中"+listStr.size()+"项");
  51. }
  52. });
  53. //取消已选
  54. btn_calcel.setOnClickListener(new OnClickListener(){
  55. @Override
  56. public void onClick(View v) {
  57. for(int i=0;i<list.size();i++){
  58. if(MyAdapter.isSelected.get(i)==true){
  59. MyAdapter.isSelected.put(i, false);
  60. listStr.remove(name[i]);
  61. }
  62. }
  63. adapter.notifyDataSetChanged();
  64. tv.setText("已选中"+listStr.size()+"项");
  65. }
  66. });
  67. }
  68. // 显示带有checkbox的listview
  69. public void showCheckBoxListView() {
  70. list = new ArrayList<HashMap<String, Object>>();
  71. for (int i = 0; i < name.length; i++) {
  72. HashMap<String, Object> map = new HashMap<String, Object>();
  73. map.put("item_tv", name[i]);
  74. map.put("item_cb", false

    );

  75. list.add(map);
  76. adapter = new MyAdapter(this, list,

    R.layout.listviewitem,

  77. new String[] { "item_tv", "item_cb" }, new int[] {
  78. R.id.item_tv, R.id.item_cb });
  79. lv.setAdapter(adapter);
  80. listStr = new ArrayList<String>();
  81. lv.setOnItemClickListener(new OnItemClickListener() {
  82. @Override
  83. public void onItemClick(AdapterView<?> arg0, View view,
  84. int position, long arg3) {
  85. ViewHolder holder = (ViewHolder) view.getTag();
  86. holder.cb.toggle();// 在每次获取点击的item时改变checkbox的状态
  87. MyAdapter.isSelected.put(position, holder.cb.isChecked()); // 同时修改map的值保存状态
  88. if (holder.cb.isChecked() == true) {
  89. listStr.add(name[position]);
  90. } else {
  91. listStr.remove(name[position]);
  92. }
  93. tv.setText("已选中"+listStr.size()+"项");
  94. }
  95. });
  96. }
  97. }
  98. //为listview自定义适配器内部类
  99. public static class MyAdapter extends BaseAdapter {
  100. ...
  101. }
  102. }

结果如下

完美解决Android在listview添加checkbox实现单选多选操作问题的更多相关文章

  1. Android在listview添加checkbox实现单选多选操作问题(转)

    转自:http://yangshen998.iteye.com/blog/1310183 在Android某些开发需求当中,有时候需要在listveiw中加入checkbox实现单选,多选操作.表面上 ...

  2. Android在listview添加checkbox实现单选多选操作问题

    android根据View的不同状态更换不同的背景http://www.eoeandroid.com/thread-198029-1-1.html android 模仿朋友网推出的菜单效果[改进版]h ...

  3. (转)完美解决 Android WebView 文本框获取焦点后自动放大有关问题

    完美解决 Android WebView 文本框获取焦点后自动放大问题 前几天在写一个项目时,要求在项目中嵌入一个WebView 本来很快就完成了,测试也没有问题.但发给新加坡时,他们测试都会出现文本 ...

  4. Android之listview添加数据篇

    一.ListView: 1. ListView通常有两个职责: 1.向布局填充数据 2.处理选择点击等操作 2.ListView的创建需要3个元素: 1. ListView中的每一列的View. 2. ...

  5. 完美解决Android SDK Manager无法更新

    由于国内的各种屏蔽现在Android SDK Manager出现无法更新或更新太慢,如下方法可完美解决此问题 1. 打开..\Android\sdk\SDK Manager.exe  2.

  6. Android中ListView结合CheckBox判断选中项

    本文主要实现在自定义的ListView布局中加入CheckBox控件,通过判断用户是否选中CheckBox来对ListView的选中项进行相应的操作.通过一个Demo来展示该功能,选中ListView ...

  7. ListView加checkBox可以实现全选等功能

    1.效果图 2.LIteView_item布局 <?xml version="1.0" encoding="utf-8"?> <Relativ ...

  8. JsTree中节点添加CheckBox 以及 单选的实现

    stree中添加checkbox,需要在初始化时设置plugins属性: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 $('#DpTree').data('jstree', fa ...

  9. checkbox的单选全选,反选,计算价格,删除

    activity_main.xml <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android&qu ...

随机推荐

  1. hadoop mapreduce 计算平均气温的代码,绝对原创

    1901 46 1902 21 1903 48 1904 33 1905 43 1906 47 1907 31 1908 28 1909 26 1910 35 1911 30 1912 16 1913 ...

  2. js页面跳转常用的几种方式(转)

    js页面跳转常用的几种方式 转载  2010-11-25   作者:    我要评论 js实现页面跳转的几种方式,需要的朋友可以参考下. 第一种: 复制代码代码如下: <script langu ...

  3. [原创]SQL表值函数:把用逗号分隔的字符串转换成表格数据

      我们日常开发过程中,非常常见的一种需求,把某一个用逗号或者/或者其他符号作为间隔的字符串分隔成一张表数据. 在前面我们介绍了 [原创]SQL 把表中字段存储的逗号隔开内容转换成列表形式,当然按照这 ...

  4. Dockerfile设置apt-get install tzdata的noninteractive方法

    在Ubuntu系统中,执行命令apt-get install -y tzdata以安装tzdata软件包.但是,最近发现,在Ubuntu 18.04 (Bionic Beaver)上无法自动安装该软件 ...

  5. Eclipse超级有用的快捷键

    1.Alt + Shift + R 重构 2.Ctrl + F11 运行并调试程序 3.Ctrl + Shift + O 自动导入包 4.Ctrl + Shift + F 格式化代码 5.F5 调试模 ...

  6. 在Android中使用Protocol Buffers(中篇)

    本文来自网易云社区. FlatBuffers 编码原理 FlatBuffers的Java库只提供了如下的4个类: ./com/google/flatbuffers/Constants.java ./c ...

  7. SQL Server2012如何打开2016的profiler文件

    SQL Server 2012如何打开2016的profiler文件 作者:markjiang7m2 原文地址:https://www.cnblogs.com/markjiang7m2/p/10980 ...

  8. java内存及数据区

    Java运行时的数据区包括:(其中前两个是线程共享的) 1.方法区(Method Area) 存储已被虚拟机加载的类信息.常量.静态变量.即时编译器编译后的代码等数据 2.堆(Heap) 存放对象实例 ...

  9. 实现html页面只自动跳转一次

    function show(){ var  value= sessionStorage.getItem("flg"); if(value==null || value==undef ...

  10. 【转】Asp.Net页面生命周期

    源地址:http://www.cnblogs.com/xhwy/archive/2012/05/20/2510178.html