Android开发人员在很多很多场合都会用到ListView这个控件,无论封装过也好,原生态也好,今天我们要说的是在ListView中关于使用Checkbox的一些让人蛋疼的问题。
此文章来自于http://www.cnblogs.com/wujd/archive/2012/08/17/2635309.html的理解,谢谢这位朋友!
1.MainActivity代码如下,简单的不用解释
public class MainActivity extends Activity {
private List<Person> list;
private ListView mListView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
initView();
//prepare data
initData();
//setting data
Adapter adapter = new Adapter(list, this);
mListView.setAdapter(adapter);
}
private void initView() {
mListView = (ListView) findViewById(R.id.lv_test);
}
private void initData() {
list = new ArrayList<Person>();
Person person;
for (int i = 0; i < 40; i++) {
person = new Person(i + "号位", Person.TYPE_NOCHECKED);
list.add(person);
}
}
}
2.我们定义一个实体类Person
public class Person {
public static final int TYPE_CHECKED = 1;
public static final int TYPE_NOCHECKED = 0;
String name;
int type;
public Person(String name, int type) {
this.name = name;
this.type = type;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
}
3.主要是我们的Adapter了
public class Adapter extends BaseAdapter {
private List<Person> mData;
private Context context;
public Adapter(List<Person> mData, Context context) {
this.mData = mData;
this.context = context;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
if (convertView == null) {
holder = new ViewHolder();
convertView = View.inflate(context, R.layout.item, null);
holder.textView = (TextView) convertView.findViewById(R.id.tv_test);
holder.checkBox = (CheckBox) convertView.findViewById(R.id.cb_test);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
//prepare data
final Person person = mData.get(position);
//设置监听器代码必须要在设置CheckBox状态之前
holder.checkBox.setOnCheckedChangeListener(new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked) {
person.setType(Person.TYPE_CHECKED);
} else {
person.setType(Person.TYPE_NOCHECKED);
}
}
});
//setting status
holder.textView.setText(person.getName());
if (person.getType() == Person.TYPE_CHECKED) {
holder.checkBox.setChecked(true);
} else {
holder.checkBox.setChecked(false);
}
return convertView;
}
@Override
public int getCount() {
return mData.size();
}
@Override
public Object getItem(int position) {
return null;
}
@Override
public long getItemId(int position) {
return 0;
}
}
class ViewHolder {
TextView textView;
CheckBox checkBox;
}
只需要记住一句话即可:设置监听器代码必须要在设置CheckBox状态之前。
错乱原因:添加监听器的代码在初始化checkBox属性的代码之后,也就是说当初始化checkBox属性时,由于可能改变其状态,导致调用了onCheckedChange()方法,而这个监听器是在上一次初始化的时候添加的,那么当然其index就是上一次的positon值,而不是本次的,所以每次保存checkBox属性状态的时候,都把值赋到的list集合里其它对象上去了,而不是与本次index相关的对象上。
解决原因:由于是因为index错误造成的,那么只要保证index值与当前positon保持一至即可,只要把添加监听器的方法加到初始化view中checkBox状态的代码之前即可.这样即始由于初始化造成调用了onCheckedChange()方法,也因为其中index值是最新的,而依然不会错乱.