關(guān)于Listview和Checkbox控件嵌套出現(xiàn)的各種問題(Recyclerview也適用)

前言


隨著安卓開發(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)儲存


最后,感謝大家閱讀本篇文章!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末漂彤,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,464評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件藤韵,死亡現(xiàn)場離奇詭異,居然都是意外死亡熊经,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,033評論 3 399
  • 文/潘曉璐 我一進(jìn)店門欲险,熙熙樓的掌柜王于貴愁眉苦臉地迎上來镐依,“玉大人,你說我怎么就攤上這事天试』笨牵” “怎么了?”我有些...
    開封第一講書人閱讀 169,078評論 0 362
  • 文/不壞的土叔 我叫張陵喜每,是天一觀的道長务唐。 經(jīng)常有香客問我,道長带兜,這世上最難降的妖魔是什么枫笛? 我笑而不...
    開封第一講書人閱讀 59,979評論 1 299
  • 正文 為了忘掉前任,我火速辦了婚禮刚照,結(jié)果婚禮上刑巧,老公的妹妹穿的比我還像新娘。我一直安慰自己无畔,他們只是感情好啊楚,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,001評論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著浑彰,像睡著了一般恭理。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上郭变,一...
    開封第一講書人閱讀 52,584評論 1 312
  • 那天颜价,我揣著相機(jī)與錄音薄风,去河邊找鬼。 笑死拍嵌,一個(gè)胖子當(dāng)著我的面吹牛遭赂,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播横辆,決...
    沈念sama閱讀 41,085評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼撇他,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了狈蚤?” 一聲冷哼從身側(cè)響起困肩,我...
    開封第一講書人閱讀 40,023評論 0 277
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎脆侮,沒想到半個(gè)月后锌畸,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,555評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡靖避,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,626評論 3 342
  • 正文 我和宋清朗相戀三年潭枣,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片幻捏。...
    茶點(diǎn)故事閱讀 40,769評論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡盆犁,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出篡九,到底是詐尸還是另有隱情谐岁,我是刑警寧澤,帶...
    沈念sama閱讀 36,439評論 5 351
  • 正文 年R本政府宣布榛臼,位于F島的核電站伊佃,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏沛善。R本人自食惡果不足惜航揉,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,115評論 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望路呜。 院中可真熱鬧迷捧,春花似錦、人聲如沸胀葱。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,601評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽抵屿。三九已至庆锦,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間轧葛,已是汗流浹背搂抒。 一陣腳步聲響...
    開封第一講書人閱讀 33,702評論 1 274
  • 我被黑心中介騙來泰國打工艇搀, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人求晶。 一個(gè)月前我還...
    沈念sama閱讀 49,191評論 3 378
  • 正文 我出身青樓焰雕,卻偏偏與公主長得像,于是被迫代替她去往敵國和親芳杏。 傳聞我的和親對象是個(gè)殘疾皇子矩屁,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,781評論 2 361