Android ListView 中加入CheckBox/RadioButton 選擇狀態保持、全選、反選實現


最近在一個項目中,需要在ListView的item中加入CheckBox,但是遇到的一個問題是上下滑動的時候如果有選擇了的CheckBox,就會出現選擇項錯誤的問題,下面將個人的解決方法總結如下;
先說思路:
在ListView的Adapter中,用一個Map保存每一項item的選擇狀態,在getView方法中,設置Map中保存的某一項的選擇狀態就實現了狀態的保存;
每一項的視圖child.xml

    <CheckBox
        android:id="@+id/item_cb"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
    <TextView
        android:id="@+id/item_tv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="hello" />

Adapter.java

public class CAdapter extends BaseAdapter {
    private List<String> list;
    private LayoutInflater inflater;
    Map<Integer, Boolean> map;
    private OnSelectedItemChanged listener;
    private Holder holder = null;

    public CAdapter(Context context, List<String> list,
            OnSelectedItemChanged listener) {
        super();
        inflater = LayoutInflater.from(context);
        this.list = list;
        map = new HashMap<Integer, Boolean>();
        for (int i = 0; i < list.size(); i++) {
            map.put(i, false);
        }
        this.listener = listener;
    }

    @Override
    public int getCount() {
        return list.size();
    }

    @Override
    public Object getItem(int position) {
        return list.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(final int position, View convertView, ViewGroup parent) {
        View view = convertView;
        String item = list.get(position);
        if (view == null) {
            holder = new Holder();
            view = inflater.inflate(R.layout.child, null);
            TextView tv = (TextView) view.findViewById(R.id.item_tv);
            CheckBox cb = (CheckBox) view.findViewById(R.id.item_cb);
            holder.tv = tv;
            holder.cb = cb;
            view.setTag(holder);
        } else {
            holder = (Holder) view.getTag();
            holder.tv.setText(item);
            holder.cb.setChecked(map.get(position));
        }
        holder.tv.setText(list.get(position));
        final CheckBox cb = holder.cb;
        cb.setChecked(map.get(position));// 設置選擇狀態
        cb.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                map.put(position, cb.isChecked());
                listener.selectedItemChange(getSelectedCount(map));
            }
        });
        return view;
    }

    /**
     * 獲取選擇的項的數目
     * 
     * @param map
     * @return
     */
    public int getSelectedCount(Map<Integer, Boolean> map) {
        int i = 0;
        for (Entry<Integer, Boolean> entry : map.entrySet()) {
            if (entry.getValue()) {
                i++;
            }
        }
        return i;
    }

    class Holder {
        TextView tv;
        CheckBox cb;
    }

    /**
     * 向Activity暴露選擇了多少項
     * 
     * @author cj
     * 
     */
    public interface OnSelectedItemChanged {
        public void selectedItemChange(int count);
    }

    public void selectAll() { // 全選 for (int i = 0; i < list.size(); i++) {
            map.put(i, true);
        }
        notifyDataSetChanged();
    }

    public void disSelectAll() { // 全不選 for (int i = 0; i < list.size(); i++) {
            map.put(i, false);
        }
        notifyDataSetChanged();
    }

    public void switchSelect() { // 反選 for (int i = 0; i < list.size(); i++) {
            boolean select = map.get(i);
            map.put(i, !select);
        }
        notifyDataSetChanged();
    }
}

MainActivity.java

public class MainActivity extends Activity {
    private ListView lv;
    private CAdapter adapter;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        lv = (ListView) findViewById(R.id.lv);
        setAdapter();

    }

    private void setAdapter() {
        List<String> list = new ArrayList<String>();
        for (int i = 0; i < 50; i++) {
            list.add("item - " + i);
        }
        adapter = new CAdapter(getApplicationContext(), list,
                new OnSelectedItemChanged() {// Adapter接口暴露出來的選擇項狀態改變時選擇的項的數目
                    @Override
                    public void selectedItemChange(int count) {
                        Log.e("SelectedCount - ", count + "");
                    }
                });
        lv.setAdapter(adapter);
    }

    // 全選
    public void selectAll(View v) {
        adapter.selectAll();
    }

    // 全不選
    public void disSelectAll(View v) {
        adapter.disSelectAll();
    }

    // 反選
    public void switchSelect(View v) {
        adapter.switchSelect();
    }
}

選擇之后反選的效果(右邊是點擊反選之后的效果):

在上面用到一個比較好的思想就是用類的內部接口向外部調用類暴露本類的一些狀態改變時,外部類可能想要獲取的數據信息;
延伸思考:上面保存的狀態是CheckBox,當需要使用RadioButton的時候,使用方法也是類似的;
但是RadioButton可能會有另一種需求{選擇某一項的時候其它項就不選擇,也即只選擇一項},此種情況其實參考上面全選,反選的實現,實現起來也是比較簡單,暫時沒時間去寫出來測試;


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM