【listview精深系列1】listview遇到checkbox碰撞出的火花

因为listview在开发中非常的常用,必须对listview研究的非常深入,才可以自定义出各种各样的效果来。并且出了问题也能想到解决措施。所以自己才有了书写listview精深系列博客的想法,自己本身也是菜鸟,,期待梳理自己的知识的同时,也可以帮助他人成长。

两个问题:

实现下面的布局很简单,但是这里面有两个问题:

问题1: 当listview滑动的时候,怎么保证checkbox选中的状态不乱掉问题2: 取消和调整按钮的监听方法如何写

取消:就是取消选择的意思。 确定:就是把选中的items的内容取到并保存到数据库中。

问题1解决方案:

我当时认为出现ListView item中有CheckBox,带来的选择状态混乱,是因为view的复用,但是当我不使用view的复用的时候,依然会出问题。其实归根结底的原因在于一旦item划出屏幕:

如果view不复用,下一次你再下拉把该item调入屏幕的时候,framework重新调用了一次getiew方法,而这个方法又把布局对象新建了一次(也就是说,如果你不复用旧的布局对象,你也再也用不了旧的布局对象了),而不是按照我们的想法:把旧的布局对象再调出来显示。所以事实上,我们以前的选中状态被清空了。 !!! 我们写的布局文件,framework都帮我们解析后建立了对应的对象实例,比如标记linnearlayout,就被系统建立成了linnearlayout对象,比如按钮标记,就被系统建立成了按钮对象。我们checkbox的选中状态,系统也会建立相应的checkbox对象,该对象的check变量为true。

如果view复用了,必然就造成checkbox的混乱了,比如第10个item复用了第一个布局对象,如果第一个布局对象选中了,那么第10个item,即使你没有选中,你也会惊讶的发现他被选中了~~~~

方法1:复用view,当选择Checkbox的时候,记下其状态,用map保存下来package com.ht.phoneguard.adapter;import android.content.Context;import android.util.Log;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.*;import com.ht.phoneguard.R;import com.ht.phoneguard.pojo.Info;import java.util.HashMap;import java.util.List;import java.util.Map;/** * Created by IntelliJ IDEA * Project: com.ht.mynote.adapters * Author: 安诺爱成长 * Email: 1399487511@qq.com * Date: 2015/5/2 */{private Context context;private List<Info> list;public Map<Integer,Boolean> mCBFlag = null;public ContactsAdapter(Context context, List<Info> list) {this.context = context;this.list = list;mCBFlag = new HashMap<Integer, Boolean>();init();}//初始化CheckBox状态void init(){for (int i = 0; i < list.size(); i++) {mCBFlag.put(i, false);}}() {return list.size();}@Overridepublic Object getItem(int i) {return list.get(i);}(int i) {return i;}@Overridepublic View getView(int i, View view, ViewGroup viewGroup) {ViewHolder viewHolder = null;if (view == null) {view = LayoutInflater.from(context).inflate(R.layout.contacts_item, null);viewHolder = new ViewHolder();viewHolder.name = (TextView) view.findViewById(R.id.name);viewHolder.number = (TextView) view.findViewById(R.id.number);viewHolder.check = (CheckBox) view.findViewById(R.id.check);view.setTag(viewHolder);}elseviewHolder = (ViewHolder) view.getTag();viewHolder.name.setText(list.get(i).getName());viewHolder.number.setText(list.get(i).getPhonenumber());viewHolder.check.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {(CompoundButton compoundButton, boolean isChecked) {if (isChecked) {mCBFlag.put(i, true);} else {mCBFlag.put(i, false);}}});/*CheckBox监听事件必须放在setChecked之前,否则后果自负*/viewHolder.check.setChecked(mCBFlag.get(i));Log.d(“position:”, “i=” + i + “,view=” + view);return view;}{private TextView name;private TextView number;private CheckBox check;}public Map<Integer, Boolean> getmCBFlag() {return mCBFlag;}(Map<Integer, Boolean> mCBFlag) {this.mCBFlag = mCBFlag;}}

对此方法更深入的分析:listview与checkbox结合,界面混乱问题:

方法2:在你的实体类中加一个标志位。判断checkbox是否点击了

问题2错误解决方案:如何清空checkbox内容(View view) {// 遍历listview的长度,将已选的按钮设为未选for (int i = 0; i < listView.getChildCount(); i++) {RelativeLayout layout = (RelativeLayout) listView.getChildAt(i);CheckBox checkBox = (CheckBox) layout.findViewById(R.id.check);if (checkBox.isChecked()) {checkBox.setChecked(false);}}}如何取到checkbox选中这一行的内容 //确定按钮的点击事件public void ensureOnClick(View view) {// 遍历listview的长度,找到选中的按钮,然后把其中的的姓名和电话取出来,存到新建的数据库中for (int i = 0; i < listView.getChildCount(); i++) {RelativeLayout layout = (RelativeLayout) listView.getChildAt(i);CheckBox checkBox = (CheckBox) layout.findViewById(R.id.check);TextView name = (TextView) layout.findViewById(R.id.name);TextView number = (TextView) layout.findViewById(R.id.number);if (checkBox.isChecked()) {//取出这条数据,然后存放到数据库中Info info = new Info();info.setName(name.getText().toString());info.setPhonenumber(number.getText().toString());DbManager.getInstance().addInfo(info);}}this.finish();}错误分析:

这个方法看上去非常的精妙,简直滴水不漏,事实上他是错误的。因为这样做只是把列表中当前可见的item项选上。清空的也是当前列表可见的item的选中状态。

为什么呢?

这得追溯到ListView.getCount() 与 ListView.getChildCount()的区别,另外还有ListView中getChildAt(index)该方法的含义。

知识讲解:ListView.getCount() 与 ListView.getChildCount()的区别

ListView.getCount()(实际上是 AdapterView.getCount()) 返回的是其 Adapter.getCount() 返回的值。也就是“所包含的 Item 总个数”。

ListView.getChildCount()(ViewGroup.getChildCount) 返回的是显示层面上的“所包含的子 View 个数”。

不会因为别人显赫的成功而促使自己有卓越的进步。

【listview精深系列1】listview遇到checkbox碰撞出的火花

相关文章:

你感兴趣的文章:

标签云: