android listView滚动时checkBox的状态不会保存的问题

在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的状态会变回原来的值问题。

刚接触不久,难免有错误,有问题欢迎提出,共同讨论交流

本文来自:http://blog.csdn.net/dxswzj/article/details/10508541
相关文章
相关标签/搜索
每日一句
    每一个你不满意的现在,都有一个你没有努力的曾经。