android 实现ListView嵌套Checkbox实现真正的多选、全选、反选、取消

android 实现ListView嵌套Checkbox实现真正的多选、全选、反选、取消

        我们在开发APP的时候,很多情况下会使用到ListView嵌套CheckBox的情况,例如购物车选择商品的情况,其实很多人要说这个其实很简单了,并没有那么复杂,事实上并非如此,我们在使用ListView嵌套CheckBox复选框的时候会出现很多问题,接下来我将用一篇博客来说明这些问题,给大家一些参照,解决ListView嵌套Checkbox解决复用问题。

        效果图如下:


首先,我们先看MainActivity中的布局,

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <ListView
        android:id="@+id/lv"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="10"
        android:divider="#808080"
        android:dividerHeight="0.1dp" />
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
       android:orientation="horizontal">

        <Button
            android:id="@+id/btn_all_select"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:text="全选" />

        <Button
            android:id="@+id/btn_all_unselect"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:text="反选" />

        <Button
            android:id="@+id/btn_delete"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:onClick="delete"
            android:text="删除" />

        <Button
            android:id="@+id/btn_cancel"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:text="取消" />
    </LinearLayout>
</LinearLayout>
接下来看MainActivity的代码如下:
package com.example.cx.listviewdemo;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.ListView;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private ListView mLv;
    private Button mBtnSelectAll, mBtnUnSelectAll, mBtnDelete, mBtnCancel;
    //数据源
    private List<String> mDataList;

    //与条目对应的选中状态
    private List<Boolean> mCheckedList;
    private MyAdapter mAdapter;
    
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
        mDataList = new ArrayList<String>();
        mCheckedList = new ArrayList<Boolean>();

        for (int i = 0; i < 50; i++) {
            mDataList.add("数据" + i);
            mCheckedList.add(false);
        }
        mAdapter = new MyAdapter(MainActivity.this, mDataList);
        mAdapter.setData(mDataList, mCheckedList);
        mLv.setAdapter(mAdapter);


        mLv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                Toast.makeText(MainActivity.this, "条目" + position + "被点击了", Toast.LENGTH_SHORT).show();

                mCheckedList.set(position, !mCheckedList.get(position));
                mAdapter.setData(mDataList, mCheckedList);
                mAdapter.notifyDataSetChanged();

            }
        });
    }

    private void initView() {
        mLv = (ListView) findViewById(R.id.lv);
        mBtnSelectAll = findViewById(R.id.btn_all_select);
        mBtnUnSelectAll = findViewById(R.id.btn_all_unselect);
        mBtnDelete = findViewById(R.id.btn_delete);
        mBtnCancel = findViewById(R.id.btn_cancel);

        mBtnSelectAll.setOnClickListener(this);
        mBtnUnSelectAll.setOnClickListener(this);
        mBtnDelete.setOnClickListener(this);
        mBtnCancel.setOnClickListener(this);
    }
    
    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            //全选
            case R.id.btn_all_select:
                select_all();
                break;

            //反选
            case R.id.btn_all_unselect:
                unselect_all();
                break;
                
            //删除
            case R.id.btn_delete:
                delete();
                break;

            //取消
            case R.id.btn_cancel:
                cancel();
                break;
        }
    }

    // 全选
    private void select_all() {
        for (int i = 0; i < mCheckedList.size(); i++) {
            mCheckedList.set(i, true);
        }
        mAdapter.setData(mDataList, mCheckedList);
        mAdapter.notifyDataSetChanged();
    }


    //取消
    private void cancel() {
        for (int i = 0; i < mCheckedList.size(); i++) {
            mCheckedList.set(i, false);
        }
        mAdapter.setData(mDataList, mCheckedList);
        mAdapter.notifyDataSetChanged();

    }

    //删除
    private void delete() {
        for (int i = 0; i < mCheckedList.size(); i++) {
            if (mCheckedList.get(i)) {
                mCheckedList.remove(i);
                mDataList.remove(i);
                i--;
            }
        }
        mAdapter.setData(mDataList, mCheckedList);
        mAdapter.notifyDataSetChanged();
    }

    //反选
    private void unselect_all() {
        for (int i = 0; i < mCheckedList.size(); i++) {
            mCheckedList.set(i, !mCheckedList.get(i));
        }
        mAdapter.setData(mDataList, mCheckedList);
        mAdapter.notifyDataSetChanged();
    }
}

主要是Adapter 的代码,里面解决了ListView 嵌套CheckBox的问题。比如,当选中item中的checkbox时然后上下滑动,这时你会发现item会被复用,什么意思呢?就是当你上下滑动listView时,选中的checkbox会被取消,这个问题跟listview加载图片时会错位一样,都是事件分发机制造成的,具体解决接下来看操作:

package com.example.cx.listviewdemo;

import android.content.Context;
import android.content.SharedPreferences;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.TextView;
import java.util.List;


public class MyAdapter extends BaseAdapter {
    private Context mContext;
    private List<String> mDataList;
    private List<Boolean> mCheckedList;
    private SharedPreferences mSp;

    public MyAdapter(Context context, List<String> mDataList) {
        this.mContext = context;
        this.mDataList = mDataList;
        mSp = mContext.getSharedPreferences("config", Context.MODE_PRIVATE);
    }


    //会被多次调用(只要ListView条目个数发生变化的时候)
    public void setData(List<String> dataList, List<Boolean> checkedList) {
        this.mDataList = dataList;
        this.mCheckedList = checkedList;
    }

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

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

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



    //图片错位: 给加载的图片设计tag(url)标记,复用之后再次滑动当前条目,判断当前图片URL和这个Tag标记是否一致,如果一致就显示,如果不一致就不显示

    @Override
    public View getView(final int position, View convertView, ViewGroup parent) {
        ViewHolder viewHolder = null;
        if (viewHolder == null) {
            viewHolder = new ViewHolder();
            convertView = View.inflate(mContext, R.layout.layout_list_item, null);
            viewHolder.mTv = convertView.findViewById(R.id.item_tv);
            viewHolder.mCb = convertView.findViewById(R.id.item_cb);
            convertView.setTag(viewHolder);

        } else {
            viewHolder = (ViewHolder) convertView.getTag();
        }

        viewHolder.mTv.setText(mDataList.get(position));
        viewHolder.mCb.setChecked(mCheckedList.get(position));

        viewHolder.mCb.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                mCheckedList.set(position, isChecked);
                notifyDataSetChanged();
            }
        });

        return convertView;
    }


    public static class ViewHolder {
        TextView mTv;
        CheckBox mCb;
    }
}
这是适配器布局代码:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="60dp"
    android:gravity="center_vertical"
    android:paddingTop="10dp"
    android:paddingBottom="10dp"
    android:descendantFocusability="blocksDescendants" //防止listview与checkbox点击造成冲突
    android:orientation="horizontal">
    
    <TextView
        android:id="@+id/item_tv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerVertical="true"
        />
    
    <CheckBox
        android:id="@+id/item_cb"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true" 
        android:layout_centerVertical="true"
        android:layout_marginRight="15dp" />

</RelativeLayout>
这样我们就实现了ListView嵌套Checkbox实现真正的多选、全选、反选、取消。

猜你喜欢

转载自blog.csdn.net/mrzhao_perfectcode/article/details/79966496