在ListView中,一般我们都会使用convertView参数,来滑动过程中,复用convertView对象来优化listView。但是如果在ListView中使用了CheckBox对象,就会出现数据错乱。比如我勾选了第一个item的CheckBox,往下滑动也会出现勾选的CheckBox。当然有些人说不优化,没次执行getView都创建一个view对象。但是那是非常不可取的,如果数据大的话,是非常要命的。本项目在实现优化的情况下,解决了CheckBox在ListView中的数据错乱,大家可以参考一下。也欢迎大家提供宝贵的意见。
activity_main.xml布局:
1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 2 xmlns:tools="http://schemas.android.com/tools" 3 android:layout_width="match_parent" 4 android:layout_height="match_parent" 5 android:orientation="vertical" > 6 7 <LinearLayout 8 android:layout_width="match_parent" 9 android:layout_height="wrap_content" 10 android:orientation="horizontal" 11 > 12 <CheckBox 13 android:id="@+id/cb_all" 14 android:layout_width="wrap_content" 15 android:layout_height="wrap_content" 16 /> 17 <Button 18 android:id="@+id/btn_del_checked" 19 android:layout_width="wrap_content" 20 android:layout_height="wrap_content" 21 android:text="@string/btn_del_checked" 22 /> 23 </LinearLayout> 24 <ListView 25 android:layout_width="match_parent" 26 android:layout_height="0dp" 27 android:layout_weight="1" 28 android:id="@+id/lv_checkbox" 29 /> 30 </LinearLayout>
activity_main_item.xml 布局:
1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 2 xmlns:tools="http://schemas.android.com/tools" 3 android:layout_width="match_parent" 4 android:layout_height="wrap_content" 5 android:gravity="left" 6 android:orientation="horizontal"> 7 <CheckBox 8 android:id="@+id/item_ck" 9 android:layout_width="wrap_content" 10 android:layout_height="wrap_content" 11 /> 12 <TextView 13 android:id="@+id/item_tv_name" 14 android:layout_width="wrap_content" 15 android:layout_height="wrap_content" 16 /> 17 </LinearLayout>
Persons.java文件
1 package com.datian.andoridlistcheck.entity; 2 3 4 public class Person { 5 6 private String name; 7 private boolean isChecked; 8 9 public Person(String name, boolean isChecked) { 10 super(); 11 this.name = name; 12 this.isChecked = isChecked; 13 } 14 15 public Person() { 16 super(); 17 } 18 19 public String getName() { 20 return name; 21 } 22 23 public void setName(String name) { 24 this.name = name; 25 } 26 27 public boolean isChecked() { 28 return isChecked; 29 } 30 31 public void setChecked(boolean isChecked) { 32 this.isChecked = isChecked; 33 } 34 35 36 }
MainActivity.java 文件
1 package com.datian.andoridlistcheck; 2 3 import java.util.ArrayList; 4 import java.util.List; 5 6 import com.datian.andoridlistcheck.adpter.CheckBoxAdpter; 7 import com.datian.andoridlistcheck.entity.Person; 8 9 import android.os.Bundle; 10 import android.app.Activity; 11 import android.content.Context; 12 import android.view.View; 13 import android.view.View.OnClickListener; 14 import android.widget.Button; 15 import android.widget.CheckBox; 16 import android.widget.ListView; 17 18 public class MainActivity extends Activity implements OnClickListener { 19 20 private Context context = this; 21 private List<Person> persons; 22 private ListView lv_checkbox; 23 private CheckBox cb_all; 24 25 private CheckBoxAdpter checkBoxAdpter; 26 27 @Override 28 protected void onCreate(Bundle savedInstanceState) { 29 super.onCreate(savedInstanceState); 30 setContentView(R.layout.activity_main); 31 initData(); 32 initWidget(); 33 } 34 35 /** 36 * 初始化控件 37 */ 38 private void initWidget() { 39 cb_all = (CheckBox) this.findViewById(R.id.cb_all); 40 cb_all.setOnClickListener(this); 41 42 43 checkBoxAdpter = new CheckBoxAdpter(context, persons,cb_all); 44 lv_checkbox = (ListView) this.findViewById(R.id.lv_checkbox); 45 lv_checkbox.setAdapter(checkBoxAdpter); 46 47 48 Button btn_del_checked = (Button) this 49 .findViewById(R.id.btn_del_checked); 50 btn_del_checked.setOnClickListener(this); 51 } 52 53 /** 54 * 初始化数据 55 */ 56 private void initData() { 57 persons = new ArrayList<Person>(); 58 for (int i = 0; i < 20; i++) { 59 persons.add(new Person("位置" + i, false)); 60 } 61 } 62 63 @Override 64 public void onClick(View v) { 65 switch (v.getId()) { 66 case R.id.btn_del_checked: // 删除选中 67 List<Person> checkedPersons = checkBoxAdpter.getCheckedPersons(); 68 for(int i = 0;i <checkedPersons.size();i++){ 69 persons.remove(checkedPersons.get(i)); 70 } 71 checkBoxAdpter.notifyDataSetChanged(); 72 break; 73 case R.id.cb_all: // 全选或全不选 74 boolean isChecked = cb_all.isChecked(); 75 for (int i = 0; i < persons.size(); i++) { 76 persons.get(i).setChecked(isChecked); 77 } 78 checkBoxAdpter.notifyDataSetChanged(); 79 break; 80 } 81 } 82 }
CheckBoxAdpter.java文件 适配器。
1 package com.datian.andoridlistcheck.adpter; 2 3 import java.util.ArrayList; 4 import java.util.List; 5 import com.datian.andoridlistcheck.R; 6 import com.datian.andoridlistcheck.entity.Person; 7 8 import android.content.Context; 9 import android.view.LayoutInflater; 10 import android.view.View; 11 import android.view.ViewGroup; 12 import android.widget.BaseAdapter; 13 import android.widget.CheckBox; 14 import android.widget.CompoundButton; 15 import android.widget.TextView; 16 17 /** 18 * @author datian 19 */ 20 public class CheckBoxAdpter extends BaseAdapter { 21 22 private LayoutInflater inflater; 23 private List<Person> persons; 24 private CheckBox cb_all; 25 public CheckBoxAdpter(Context context, List<Person> persons, CheckBox cb_all) { 26 this.inflater = LayoutInflater.from(context); 27 this.persons = persons; 28 this.cb_all = cb_all; 29 } 30 31 @Override 32 public int getCount() { 33 return persons.size(); 34 } 35 36 @Override 37 public Object getItem(int position) { 38 return persons.get(position); 39 } 40 41 @Override 42 public long getItemId(int position) { 43 return position; 44 } 45 46 47 @Override 48 public View getView(int position, View convertView, ViewGroup parent) { 49 final int pos = position; 50 HanlderView hanlderView = null; 51 if(convertView==null){ 52 hanlderView = new HanlderView(); 53 convertView = inflater.inflate(R.layout.activity_main_item, null); 54 hanlderView.item_ck = (CheckBox) convertView.findViewById(R.id.item_ck); 55 hanlderView.item_tv_name = (TextView) convertView.findViewById(R.id.item_tv_name); 56 convertView.setTag(hanlderView); 57 }else{ 58 hanlderView = (HanlderView) convertView.getTag(); 59 } 60 61 hanlderView.item_ck.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { 62 @Override 63 public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 64 persons.get(pos).setChecked(isChecked); 65 System.out.println("listener------"+persons.get(pos).getName()+":"+isChecked); 66 if(isCheckedAll()){ 67 cb_all.setChecked(true); 68 }else{ 69 cb_all.setChecked(false); 70 } 71 } 72 }); 73 74 hanlderView.item_ck.setChecked(persons.get(pos).isChecked()); 75 System.out.println("list----"+pos+":"+persons.get(pos).isChecked()); 76 hanlderView.item_tv_name.setText(persons.get(position).getName()); 77 return convertView; 78 } 79 80 /** 81 * 获取被选中 82 * @return 被选中的集合list 83 */ 84 public List<Person> getCheckedPersons(){ 85 List<Person> checkedPersons = new ArrayList<Person>(); 86 for(int i = 0;i<persons.size();i++){ 87 if(persons.get(i).isChecked()){ 88 checkedPersons.add(persons.get(i)); 89 } 90 } 91 return checkedPersons; 92 } 93 94 /** 95 * 判断是否全部选中 96 * @return 97 */ 98 private boolean isCheckedAll(){ 99 boolean flag = true; 100 for(int i = 0;i < persons.size();i++){ 101 if(!persons.get(i).isChecked()){ 102 flag = false; 103 break; 104 } 105 } 106 return flag; 107 } 108 109 private class HanlderView{ 110 public CheckBox item_ck; 111 public TextView item_tv_name; 112 } 113 }
hanlderView.item_ck.setChecked(persons.get(pos).isChecked());这行必须要在setOnCheckedChangeListener监听的后面才行。