在android开发中listView与checkbox的结合 会出现各种大大小小的问题,在实际开发中得多注意。
ListView上有checkBox、button时导致onListItemClick方法失效的解决办法 可以点击看这里
问题描述:
解决好onListItemClikc失效问题后 你又会发现一个问题:当listview滚动时checkBox的状态会变回原来的值,
比如一个listview有个id为1的checkBox,刚进来的时候是没选上的,然后你把它选上,这时你滚动listview至这个checkBox不出现在可视范围内,然后再拉回来 你会发现该checkBox状态又变为未选择。
原因分析:
listview滚动时会去掉用adapter的getView(final int position, View convertView, ViewGroup parent)方法,重新渲染item,这时会调用原来值取赋值,所以导致你刚才做的选择无效掉,
adapter的getView方法简单介绍下:
listview滚动时会根据当前页面中新item出现的次数去多次调用getView方法,每新出现一个item就会调用一次getView方法,看下面的图
当有左边的状态 滚动到右边的状态时,我在getView方法里打印出文字,结果如下
解决方法:
知道原因后就好解决了,肯定要从getView方法入手,
解决思路:1.重写Adapter的getView方法
2.在getView方法里用HashMap<Integer, Boolean> map记录当前位置的checkBox的状态(key为当前item在listview的位置,value为checkbox的状态)
3.当item回滚回来时去map里查看该位置的的状态,如果是选中的话 重新选中,否则不选中;
还是贴上关键代码把:
list.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/llUserList"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:descendantFocusability="blocksDescendants">
<CheckBox
android:id="@+id/ckUser"
android:focusable="false"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
<ImageView
android:id="@+id/imgUserImg"
android:contentDescription="头像"
android:layout_weight="1"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/tvUserName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="2"
/>
<TextView
android:id="@+id/tvUserMoney"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="2"/>
</LinearLayout>
UserAdapter继承BaseAdap,在这里重写getView方法:
public class UserAdapter extends BaseAdapter{
}
getView方法里的代码:(要根据自己的情况改动)
/**
* 重写getView 滚动的时候会 调用该方法
* 重新后解决了 滚动listview导致 checkbox选择后 勾选无效的问题(checkbox状态变回原来的状态)
*/
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
LayoutInflater mInflater = LayoutInflater.from(context);
convertView = mInflater.inflate(R.layout.user_list, null);
//给item重新赋值
ImageView imgUserImg = (ImageView) convertView.findViewById(R.id.imgUserImg);
imgUserImg.setBackgroundResource((Integer) listData.get(position).get("imgUserImg"));
TextView tvUserName = (TextView) convertView.findViewById(R.id.tvUserName);
tvUserName.setText((String)listData.get(position).get("tvUserName"));
Log.d("getView", (String)listData.get(position).get("tvUserName"));
TextView tvUserMoney = (TextView) convertView.findViewById(R.id.tvUserMoney);
tvUserMoney.setText(String.valueOf(listData.get(position).get("tvUserMoney")));
CheckBox check = (CheckBox) convertView.findViewById(R.id.ckUser);
// check.setChecked(Boolean.parseBoolean((String)listData.get(position).get("ckUser")));
check.setOnCheckedChangeListener(new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
if (isChecked) {
state.put(position, isChecked);
listData.get(position).put("ckUser","true");
} else {
state.remove(position);
listData.get(position).put("ckUser","false");
}
}
});
check.setChecked(state.get(position)==null?false:true);
return convertView;
}
(以上代码虽然解决了问题,但存在性能问题,想想每次getView 的时候都实例化layout 效率非常低 ,而且下面每次 都new 好几个view,这样数据一多,多滚动性能肯定是要出问题,但为了给像我一样的初学者看的比较顺眼,就先这样写, 要看getView优化后的代码 请点击这里查看)
然后在绑定adapter到listview
我这里是继承ListFragment,所以直接在需要的地方 调用 setListAdapter(getUserAdapter());
public class UserListFragment extends ListFragment{
//保存listView里的数据
private ArrayList<HashMap<String,Object>> arrayList = new ArrayList<HashMap<String,Object>>();
private LinearLayout llUserList;
private MainUserAdapter userAdapter;
public MainUserAdapter getUserAdapter(){
if(userAdapter==null){
userAdapter = new MainUserAdapter(getActivity().getApplicationContext(),arrayList);
}
return userAdapter;
}
@Override
public void onResume() {
// TODO Auto-generated method stub
super.onResume();
reflashList();
System.out.println("Fragment-->onResume");
}
public void reflashList(){
//这里设置arrayList 的值
........
setListAdapter(getUserAdapter());
}
.......
}
这样就可以解决listview滚动时checkBox的状态会变回原来的值问题。
刚接触不久,难免有错误,有问题欢迎提出,共同讨论交流