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




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章