ListView加CheckBox簡單實現批量刪除

前段時間要做一個批量刪除的功能,身爲初學者的我,開始嘗試做這個功能,但是出現了以下3個情況:

  1. checkbox被勾選上後,listview滑走再滑回來,本來應該被選中的checkbox成了未選中狀態
  2. 連續勾選後,刪除的不完整,比如我同時勾上了第3、4、5個item,點擊刪除後第3、5個倒是被刪除了,第4個沒有被刪除
  3. 亂序,明明選擇的是第2個,點擊刪除的時候,隨機的一個被刪除了

本來在網上查了一些解決的方法,但是都太複雜了(個人感覺),一個簡單的批量刪除,居然用map這麼高級的東西,所以我分享一下我解決的方法。
先上效果圖:
批量刪除效果圖
界面超級簡單,完全是爲了做批量刪除而的一個小例子,也沒有夾雜一些別的東西,比如全選反選之類的,我喜歡一篇文章只說一個問題,

使用到的類

  1. MainActivity:不解釋
  2. MyAdapter:listview的適配器
  3. Entity:實體類,封裝了listview的item的內容

接下來一個一個解釋,每個類到底有什麼東西
先說最簡的Entity
代表着每一個item的內容

//是否被選中
private boolean isSelect;
//文本內容
private String text;

就兩個屬性,別的都是一些get、set方法,tostring什麼的。

接下來是MyAdapter類:
繼承BaseAdapter,實現對應的4個方法
以下是繼承BaseAdapter的常見手段(方法)

    private ArrayList<Entity> datas = new ArrayList<>();
    private LayoutInflater inflater;

    public MyAdapter(Context context) {
        inflater = LayoutInflater.from(context);
    }

    public void setList(ArrayList<Entity> list) {
        this.datas = list;
    }

現在說說最重要的getView方法

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        //使用viewholder優化listview
        ViewHolder holder;

        if (convertView == null) {
            convertView = inflater.inflate(R.layout.item, null);
            holder = new ViewHolder(convertView);
            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }

        //將position傳遞給checkbox監聽的實現類
        //說白了就是讓chechbox知道它在listview的哪個位置
        //好處就是,刪除的時候不會亂了,不會因爲選中的是a而把b刪了(解決亂序)
        //因爲checkbox知道自己的位置了嘛
        holder.checkbox.setTag(position);
        holder.text.setText(datas.get(position).getText());

        //給checkbox設置監聽
        //使他被選中的時候做一些事情
        //比如將對應的entity的isSelect改爲true
        holder.checkbox.setOnCheckedChangeListener(listener);

        //給checkbox設置狀態,是否被選中
        //通過獲取對應的entity,取得裏面的isSelect的值修改
        //解決選中後,listview滑動走再滑回來,checkbox又沒有選的尷尬
        holder.checkbox.setChecked(datas.get(position).isSelect());

        return convertView;
    }

    private CompoundButton.OnCheckedChangeListener listener = new CompoundButton.OnCheckedChangeListener() {
        @Override
        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
            //獲取傳遞來的position,點擊listview列表中的checkbox的時候,就能知道是點擊的哪個了
            int pos = (int) buttonView.getTag();
            //將集合中對應的entity中對應的isSelect設置爲checkbox的狀態(是否被選中true/false)
            getItem(pos).setSelect(isChecked);
        }
    };

    public static class ViewHolder {
        public View rootView;
        public TextView text;
        public CheckBox checkbox;

        public ViewHolder(View rootView) {
            this.rootView = rootView;
            this.text = (TextView) rootView.findViewById(R.id.text);
            this.checkbox = (CheckBox) rootView.findViewById(R.id.checkbox);
        }

    }

準備工作都做完了,我們來看看MainActivity中的具體實現
佈局很簡單,線性佈局,方向垂直,上面一個批量刪除的按鈕,下面是listview。
先來感受一下MainActivity裏面的內容:

public class MainActivity extends AppCompatActivity  {

    private ListView listview;
    private Button del;
    private MyAdapter adapter;

    private ArrayList<Entity> datas;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        datas = new ArrayList<>();

        for (int i = 0; i < 30; i++) {
            datas.add(new Entity(false, "item" + i));
        }

        listview = (ListView) findViewById(R.id.listview);
        del = (Button) findViewById(R.id.del);

        adapter = new MyAdapter(this);
        adapter.addData(datas);
        listview.setAdapter(adapter);

        del.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                ArrayList<Entity> data = adapter.getData();

                for (int i = 0; i < data.size(); i++) {
                    if (data.get(i).isSelect()) {
                        data.remove(i);
                        i--;
                    }
                }
                adapter.setList(data);
                adapter.notifyDataSetChanged();

            }
        });

    }

}

別的都沒上什麼說的,我們來看看點擊事件裏面有個i - -,這是幹嘛的呢,爲什麼要這麼寫呢,不寫會有什麼後果呢?
不寫的後果很嚴重,就是連續勾選item後,點擊刪除,不會全部被刪除,爲什麼會這樣,這要牽扯到ArrayList的結構。大家都知道ArrayList是類似數組的結構,所以,
來看一張我用畫圖工具畫的渣圖
ArrayList
該圖表示arraylist中有很多數據,其中梨子的位置是1,香蕉的位置是2,當我們刪除了梨子後,本來應該第2的香蕉,變成的位置1,也就是梨子後面所有的數據都想前挪動了一位(感覺好耗資源啊)

所以當我們連續選擇又沒有i- -時候,畫圖最清楚,上圖!
這裏寫圖片描述
這裏解釋下:

圖1:當我們選中234的時候,實際上是將每一個item對應的entity中的isSelect值改爲了true。

圖2:點擊刪除後,系統開始循環遍歷整個集合,爲true就刪除,該循環只執行一次,
所以當循環到了位置2的時候,發現是true,不解釋直接刪除,此時集合中的數據位置爲圖2,
位置2已被item3代替

圖3:繼續循環,到了位置3,發現是item4,一看值爲true,直接刪,此時集合中的數據位置爲圖3

所以最終結果就是item3瞞天過海了。。。

結論

在for循環中,我們指定了循環的次數,int times = date.size(),但是當我們刪除了集合中的一個數據後,times已經發生改變了,爲了不使他改變,刪除一個就i- -一次,這樣,就能保證循環的次數和集合尺寸一樣了,就能完美實現批量刪除了。

源碼

http://download.csdn.net/detail/it_xf/9569331

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章