前言
隨著安卓開發(fā)的深入了解,越來越發(fā)現(xiàn),很多看似簡單的東西,在沒有思路的情況下,盲目去寫,會發(fā)現(xiàn)寫到最后,連自己都感覺各種漏洞和問題,
其實(shí)這個(gè)問題也是我的親身經(jīng)歷, 當(dāng)初我在面對Listview和Checkbox控件的嵌套問題的時(shí)候,我發(fā)現(xiàn)我處理的很差,很多問題,而且有特別不好改,主要原因是自己的思路沒有建立起來,去借鑒別人的代碼,導(dǎo)致我很長時(shí)間都不敢再去動那個(gè)頁面.
最近偶然一次機(jī)會,別人問到過這個(gè)問題,我也是硬著頭皮重新去回憶這個(gè)問題,突然發(fā)現(xiàn),以前還是經(jīng)驗(yàn)太少,不敢去面對自己出現(xiàn)的問題,現(xiàn)在我也跟大家分享一下我的心理歷程和關(guān)于這個(gè)問題解決的心得.
問題點(diǎn):
第一個(gè):關(guān)于Listview和Checkbox的復(fù)用問題
如果大家是第一次遇到這個(gè)問題的話,沒有一個(gè)好的思路,確實(shí)是難以下手,在心理上就已經(jīng)被嚇怕了,其實(shí)是沒有必要的,越是這樣情況下,你越是要冷靜,慢慢去理清頭緒.
我們知道,listview的復(fù)用問題很常見,在這里我重點(diǎn)說下思路,要知道每個(gè)item里面都有一個(gè)chekcbox,如果我有20個(gè)item,我選中的第一個(gè)item的checkbox,那么下面一定會有一個(gè)item會跟第一個(gè)item進(jìn)行復(fù)用,對吧?那怎么辦呢?
別急,為什么會產(chǎn)生這個(gè)問題,我們可以從三個(gè)地方思考:
第一個(gè),能不能不讓條目復(fù)用?每一個(gè)都
獨(dú)一無二
?
第二個(gè),能不能只讓checkbox不復(fù)用,item還是復(fù)用?
第三個(gè),checkbox的選中狀態(tài)也是一種數(shù)據(jù)(true/false
),我能不能讓數(shù)據(jù)不復(fù)用(也就是具有唯一性
)?
情況分析:
第一種情況,肯定不可取的,因?yàn)椴贿M(jìn)行復(fù)用,如果條目多了,會導(dǎo)致OOM.這可得不償失.所以第一種情況是不可取的.
第二種情況,checkbox不復(fù)用,這種說法是不成立的,因?yàn)閏heckbox依附item中,沒法做到讓其中單獨(dú)復(fù)用!
事實(shí)上,大家一看就知道第三種,就有很多種思路了把?就是讓每個(gè)checkbox的選中狀態(tài)的值都是唯一的,這樣就不會導(dǎo)致復(fù)用的時(shí)候出現(xiàn)選一個(gè)而選多個(gè)的情況了!
下面我貼出我自己的寫的一個(gè)例子,供大家參考!!
private class MyAdapter extends MyBaseAdapter<String> {
HashMap<Integer, Boolean> hashMap = new HashMap<>();
public MyAdapter(List dataList) {
super(dataList);
initMap(dataList);
}
/**
*初始化map集合,將所有checkbox默認(rèn)設(shè)置為false
*/
private void initMap(List dataList) {
if (!dataList.isEmpty()) {
for (int i = 0; i < dataList.size(); i++) {
hashMap.put(i, false);}
}
}
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
holder = new ViewHolder();
convertView = View.inflate(UIUtils.getContext(), R.layout.item_listview, null);
holder.mtv = (TextView) convertView.findViewById(R.id.textview);
holder.mCheckbox = (CheckBox) convertView.findViewById(R.id.checkbox);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.mtv.setText(mDataList.get(position));
holder.mCheckbox.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
CheckBox checkbox = (CheckBox) v;
if (checkbox.isChecked()) {
hashMap.put(position,true);//每個(gè)position為唯一索引,進(jìn)行存和取
}else{
hashMap.put(position,false);//每個(gè)position為唯一索引,進(jìn)行存和取
}
}
});
holder.mCheckbox.setChecked(hashMap.get(position)); //設(shè)置checkbox的狀態(tài)
return convertView;
}
public class ViewHolder {
CheckBox mCheckbox;
TextView mtv;
}
}
item的布局很簡單,就是一個(gè)checkbox和textview,以上主要實(shí)現(xiàn)的邏輯是:
所有的checkbox狀態(tài)都用一個(gè)map集合存起來,
在頁面加載時(shí)候,在適配器的構(gòu)造函數(shù)中需要對map集合進(jìn)行初始化(所有的checkbox默認(rèn)選中是false)
當(dāng)你點(diǎn)擊checkbox的時(shí)候,我們?nèi)ブ匦略O(shè)置checkbox的狀態(tài),然后獲取,這樣就能夠完美的解決復(fù)用問題了
第二個(gè)關(guān)于Listview和Checkbox的單選,多選問題
我們剛剛解決了復(fù)用問題,相信大家對這個(gè)問題已經(jīng)不再無從下手了.關(guān)于Listview和Checkbox的多選問題,其實(shí)上面的代碼,完全不動就已經(jīng)實(shí)現(xiàn)多選功能了,因此,可能對某些需求來講,比如,我只想單選的話,多選可能是一個(gè)bug,(哈哈,開個(gè)玩笑!)
我們重點(diǎn)說一下checkbox的單選問題. 其實(shí)這個(gè)問題也不難,看看你能不能夠想通了~! 單選其實(shí)就是你在點(diǎn)擊某個(gè)checkbox的時(shí)候, 讓上次選中的狀態(tài)全部變成false的狀態(tài)對吧? 那么我們何時(shí)在點(diǎn)擊選中的時(shí)候,就將每個(gè)checkbox的狀態(tài)全部置為false呢?這樣, 不管你選中還不選中,都能做到單向選擇啦!!所以選擇一個(gè)適當(dāng)?shù)臅r(shí)機(jī)很重要获印。
因此我們只需要在這里加上2行代碼就可以完美解決了!!!
holder.mCheckbox.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
CheckBox checkbox = (CheckBox) v;
initMap(mDataList); //清空之前所有的選擇
notifyDataSetChanged(); //刷新適配器
if (checkbox.isChecked()) {
hashMap.put(position,true);
}else{
hashMap.put(position,false);
}
}
});
第三個(gè):關(guān)于Listview和Checkbox會搶占焦點(diǎn)的問題(也就是Checkbox的點(diǎn)擊事件被攔截)
如果有人會遇到這個(gè)問題,其實(shí)只要加一個(gè)屬性就好了.就可以完美的解決checkbox點(diǎn)擊和listview的點(diǎn)擊事件會干擾的問題.
我們需要在item的根布局加上一個(gè)屬性!!
android:descendantFocusability="blocksDescendants"
就可以完美解決了!!
好了,關(guān)于Listview和Checkbox嵌套的問題就講到這里,如果我說的這個(gè)解決方案能夠幫助到你, 那么請給我點(diǎn)個(gè)贊把!如果我當(dāng)前有寫的不好的地方,歡迎指出!
PS: 以上的解決方案,作為當(dāng)時(shí)初入安卓, 可能解決方案并不太理想,下面提供幾個(gè)更方便的思路!
1. 在item里加個(gè)字段斩个,具體操作了解下ObservableArrayList
2. 聽說也可以在holder中保留一個(gè)bool值進(jìn)行狀態(tài)儲存
最后,感謝大家閱讀本篇文章!