前言
說下前幾天遇到的一個小問題,關於RecyclerView條目選中狀態的保存.眾所周知,RecyclerView被創造出來用於條目的回收利用,但是,當前面回收的條目帶有一些特殊的狀態(區別於未選中狀態),那么滑動的時候,后面的條目會重復這些狀態,於是你的視圖就完全混亂了,這並不是你想要的效果,那么就很有必要來談談這個選中狀態的復用了.
此外,條目的選中與未選中狀態,類似於一個CheckBox的勾選狀態,我們不妨假設RecyclerView列表條目中有一個CheckBox(可以根據這個CheckBox的勾選狀態來顯示不同的視圖,CheckBox的樣式很靈活,不影響你的布局效果),那么關於CheckBox的狀態保存就是現在要討論的問題了.
分析
CheckBox有它自己的選中監聽,選中狀態isChecked=true時,你可以顯示選中視圖;非選中狀態isChecked=false時,你可以顯示非選中視圖;單個條目的選中狀態是沒有問題的,一旦滑動,那么問題就來了,后面未選中的條目復用了之前的條目的選中狀態,於是就造成了混亂.
如果我們記錄並儲存位置和選中的狀態,在RecyclerView.Adapter的onBindViewHolder中,根據當前position去取出該位置的狀態,然后根據狀態來顯示相應的視圖,就能搞定了.
還有一種做法也很容易想到,那就是把CheckBox的選中狀態作為填充數據bean的一個字段屬性,那么每次創建條目,即走onBindViewHolder方法時,都拿出bean中的isChecked屬性,根據這個屬性來判斷當前應該顯示什么樣的視圖.
實現
說下自己的實現方式吧,按常理應該用個雙列集合map來保存位置和選中的狀態,我不想這么做,我用一個List<Integer> posList來記錄選中的位置,再在RecyclerView.Adapter的onBindViewHolder中判斷當前的position是否在這個集合中,然后
mHolder.cb.setChecked(posList.contains(position) ? true : false);這樣就可以正常顯示選中條目的視圖了;值得注意的是在CheckBox的選中事件中動態地根據選中與否來到posList集合中添加或異常該position.
Talk is cheap , show me the code.
mHolder.cb.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton compoundButton, boolean b) { mHolder.iv_state.setImageResource(b ? R.drawable.selected : R.drawable.unchecked); if (b) { if (!posList.contains(position)) { posList.add(position); } //數據操作 } else { if (posList.contains(position)) { int i = posList.indexOf(position); posList.remove(i); } //數據操作 } } }); mHolder.cb.setChecked(posList.contains(position) ? true : false);
總結
以前遇到問題,總是沒有去梳理、記錄和總結 , 弄得好像每次都是遇到一個新問題一樣 , 這個問題我記得處理過多次了.分析其原理,總結應對方法, 希望下次再碰到 , 能信手拈來 , 游刃有余...