在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的狀態會變回原來的值問題。
剛接觸不久,難免有錯誤,有問題歡迎提出,共同討論交流