ListView+CheckBox实现全选,全不选功能

原创 2016年08月31日 10:08:11

ListView+CheckBox实现全选,全不选功能

项目中有一个需求,选择联系人进行发送消息,可以实现全选,或者全不选,或者取消某一个已选中的.当点击确定按钮时,获取到已勾选的联系人信息.这里先来一张效果图:

这里写图片描述

点击确定按钮后,输出已勾选联系人信息.
这里写图片描述

这里先把几个关键地方提一下:

  • listView+checkBox时,listView的item焦点会失去点击效果

    • 原因:开发中很常见的一个问题,项目中的listview不仅仅是简单的文字,常常需要自己定义listview,自己的Adapter去继承BaseAdapter,在adapter中按照需求进行编写,问题就出现了,可能会发生点击每一个item的时候没有反应,无法获取的焦点。原因多半是由于在你自己定义的Item中存在诸如ImageButton,Button,CheckBox等子控件(也可以说是Button或者Checkable的子类控件),由于这些控件是强焦点控件,此时这些控件会抢占Item的焦点,所以常常当点击item时变化的是子控件,item本身的点击没有响应。解决方法有很多种,如使用焦点比较弱的控件,或者自己去处理事件分发来解决焦点冲突。下面给大家介绍一种比较简单的方法。
    • 解决方法:在listView 的item 布局的顶层布局中 添加属android:descendantFocusability=”blocksDescendants”,就可以很简单的解决了。
      - 我们看一下android:descendantFocusability属性:API描述如下:

      android:descendantFocusability

      Defines the relationship between the ViewGroup and its descendants when looking for a View to take focus.
      Must be one of the following constant values.

      该属性是当一个为view获取焦点时,定义viewGroup和其子控件两者之间的关系。

      属性的值有三种:

      beforeDescendants:viewgroup会优先其子类控件而获取到焦点

      afterDescendants:viewgroup只有当其子类控件不需要获取焦点时才获取焦点

      blocksDescendants:viewgroup会覆盖子类控件而直接获得焦点

  • 当点击Item时,CheckBox实现联动效果(上一步已经处理了Item的焦点)

    • 只需要添加ListView的点击事件,在点击事件中实现CheckBox联动效果。伪代码:
 @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        TestCheckAllAdapter.ViewHolder holder = (TestCheckAllAdapter.ViewHolder) view.getTag();
        // 会自动触发CheckBox的checked事件
        holder.checkBox.toggle();
    }
  • 修改CheckBox的样式

    • 首先,我们定义一个状态选择器(两张图片,一张是normal状态,另一种是pressed状态):

      • <?xml version="1.0" encoding="utf-8"?>
        <selector
        xmlns:android="http://schemas.android.com/apk/res/android">
        <item android:state_checkable="true" android:drawable="@drawable/checkbox_pressed" />
        <item android:state_checked="true" android:drawable="@drawable/checkbox_pressed" />
        <item android:state_pressed="true" android:drawable="@drawable/checkbox_pressed" />
        <item android:drawable="@drawable/checkbox_normal" />
        </selector>
    • 然后在style布局中添加CheckBox样式:

      • <!--自定义CheckBox的样式-->
        <style name="CustomCheckboxTheme" parent="@android:style/Widget.CompoundButton.CheckBox">
        <item name="android:button">@drawable/selector_checkbox</item>
        </style>
    • 最后,在布局中引入自定义CheckBox样式:

      • <CheckBox
        android:id="@+id/cb_check"
        style="@style/CustomCheckboxTheme"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:focusable="false" />

全选,全不选实现

这里就不细说了,代码中注释很详细.

Activity类:

/**
 * Created by ListenerGao on 2016/8/29.
 * <p/>
 * listView实现全选,全不选功能
 */
public class TestCheckAll extends BaseActivity implements AdapterView.OnItemClickListener {
    private static final String TAG = "TestCheckAll";
    @BindView(R.id.tv_check)
    TextView tvCheck;
    @BindView(R.id.lv_check)
    ListView lvCheck;
    @BindView(R.id.ib_arrow_left)
    ImageButton ibArrowLeft;
    @BindView(R.id.bt_confirm)
    Button btConfirm;

    private List<TestCheckBean> mData;
    private TestCheckAllAdapter mAdapter;

    @Override
    protected int getLayoutResId() {
        return R.layout.activity_test_checkall;
    }

    @Override
    protected void initView() {
        ButterKnife.bind(this);
        tvCheck.setVisibility(View.VISIBLE);
        tvCheck.setText("全选");
        ibArrowLeft.setVisibility(View.VISIBLE);
    }

    @Override
    protected void initData() {
        //初始化数据
        mData = new ArrayList<>();
        for (int i = 0; i < 15; i++) {
            TestCheckBean testCheckBean = new TestCheckBean(i, "张三" + i);
            mData.add(testCheckBean);
        }
        mAdapter = new TestCheckAllAdapter(this, mData);
        lvCheck.setAdapter(mAdapter);

        lvCheck.setOnItemClickListener(this);

    }


    @OnClick({R.id.ib_arrow_left, R.id.tv_check, R.id.bt_confirm})
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.ib_arrow_left:
                finish();
                break;
            case R.id.tv_check:
                if (tvCheck.getText().equals("全选")) {
                    mAdapter.initCheckBox(true);
                    mAdapter.notifyDataSetChanged();
                    tvCheck.setText("全不选");
                } else if (tvCheck.getText().equals("全不选")) {
                    mAdapter.initCheckBox(false);
                    mAdapter.notifyDataSetChanged();
                    tvCheck.setText("全选");
                }
                break;

            case R.id.bt_confirm:
                //得到选中状态条目的数据Bean
                Map<Integer, Boolean> checkedMap = mAdapter.getCheckedMap();
                List<TestCheckBean> allChecked = new ArrayList<>();
                for (int i = 0; i < checkedMap.size(); i++) {
                    if (checkedMap.get(i)) {
                        TestCheckBean testCheckBean = mData.get(i);
                        allChecked.add(testCheckBean);
                    }
                }
                //遍历输出已勾选条目的数据Bean
                for (TestCheckBean bean : allChecked) {

                    Log.d(TAG, bean.toString());
                }
                break;
        }
    }

    /**
     * listView+checkBox时,listView的item焦点会失去点击。
     * 需要在listView 的item 布局的顶层布局中 添加属性:android:descendantFocusability="blocksDescendants"
     * 当点击item时checkBox实现联动效果
     */
    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        TestCheckAllAdapter.ViewHolder holder = (TestCheckAllAdapter.ViewHolder) view.getTag();
        // 会自动触发CheckBox的checked事件
        holder.checkBox.toggle();
    }
}

Adapter类:

/**
 * Created by ListenerGao on 2016/8/29.
 */
public class TestCheckAllAdapter extends BaseAdapter {
    private Context mContext;
    private List<TestCheckBean> mData;
    //存储CheckBox状态的集合
    private Map<Integer,Boolean> checkedMap;

    public TestCheckAllAdapter(Context context, List<TestCheckBean> data) {
        this.mContext = context;
        this.mData = data;
        checkedMap = new HashMap<>();
        //默认CheckBox为未勾选状态
        initCheckBox(false);
    }

    /**
     * 初始化Map集合
     * @param isChecked   CheckBox状态
     */
    public void initCheckBox(boolean isChecked) {
        for (int i = 0; i<mData.size();i++) {
            checkedMap.put(i,isChecked);
        }
    }

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

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

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

    @Override
    public View getView(final int position, View convertView, ViewGroup parent) {
        ViewHolder holder;
        if (convertView == null) {
            convertView = LayoutInflater.from(mContext).inflate(R.layout.item_test_checkall,null);
            holder = new ViewHolder(convertView);
            convertView.setTag(holder);
        }else {
            holder = (ViewHolder) convertView.getTag();
        }
        holder.tvName.setText(mData.get(position).getName());
        // 勾选框的点击事件
        holder.checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                // 当勾选框状态发生改变时,重新存入map集合
                checkedMap.put(position,isChecked);
            }
        });
        //设置勾选框的状态
        holder.checkBox.setChecked(checkedMap.get(position));
        return convertView;
    }

    /**
     * 得到勾选状态的集合
     * @return
     */
    public Map<Integer,Boolean> getCheckedMap() {
        return checkedMap;
    }

    public static class ViewHolder{
        @BindView(R.id.tv_name)
        public TextView tvName;
        @BindView(R.id.cb_check)
        public CheckBox checkBox;

        public ViewHolder(View view) {
            ButterKnife.bind(this,view);
        }
    }
}

源码地址:
https://github.com/ListenerGao/MyTest/blob/master/app/src/main/java/com/listenergao/mytest/activity/TestCheckAll.java

版权声明:本文为博主原创文章,未经博主允许不得转载。

基于ListView和CheckBox实现多选和全选记录的功能

http://blog.csdn.net/zuolongsnail/article/details/7051620 应用开发中经常会有从数据库中读取数据显示,然后选中多条、全部记录并...
  • daditao
  • daditao
  • 2014年05月15日 21:30
  • 2604

Android 带checkbox的listView 实现多选,全选,反选

Demo地址(0分资源):http://download.csdn.net/detail/onlyonecoder/5154352 由于listview的一些特性,刚开始写这种需求的功能的时候都会...
  • OnlyOneCoder
  • OnlyOneCoder
  • 2013年03月18日 16:38
  • 38855

android完美解决ListView中CheckBox的全选、反选、批量删除的问题

效果图 前几天看到有朋友发帖问关于ListView的多选、反选、取消等问题,我自己想了一下,最好的解决方法应该是生成一个list来维系checkbox组的选择状态。利用listview的getChi...
  • selfreeyuan
  • selfreeyuan
  • 2016年02月24日 12:04
  • 5644

Android开发ListView中包含CheckBox(点击item选中CheckBox),并设置其全选反选等功能

要实现ListView中CheckBox的选中并记录,我的做法是自己写一个Adapter,继承于BaseAdapter,ListView中的CheckBox需要将focusable,clickable...
  • nmzkchina
  • nmzkchina
  • 2012年08月10日 15:58
  • 3409

安卓ListView中CheckBox的使用(支持Item列表项的删除,全选,全不选)

ListView 自身提供了 CheckBox 只需要添加一行代码 getListView().setChoiceMode(ListView.CHOICE_MODE_MULTIPLE); ...
  • jiankeufo
  • jiankeufo
  • 2015年02月06日 10:56
  • 841

自定义Adapter、全选、反选、checkbox、

package com.example.administrator.myweidget.adapter;import android.util.Log; import android.view.Lay...
  • F1186485056
  • F1186485056
  • 2015年08月25日 21:41
  • 447

checkbox全选 全不选 所有的子项选中或者不全选中后,全选按钮也选中或者不选中

1,jsp 页面         全选            苹果      草莓      西瓜      菠萝   2,js     $(function(){ ...
  • yanlove_jing
  • yanlove_jing
  • 2015年03月13日 17:28
  • 5371

checkbox全选全不选、子chekbox全选非全选对应父checkbox选不选——全

jQuery实现CheckBox全选、全不选 $(function() { $("#checkAll").click(function() { ...
  • superit401
  • superit401
  • 2016年07月08日 16:40
  • 2477

android ListView中Checkbox实现单选,全选,全不选功能

@Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub...
  • jdsjlzx
  • jdsjlzx
  • 2011年11月14日 17:06
  • 11036

ListView+CheckBox UI 完美版。实现 全选 、 全不选 、 删除等功能

  • 2014年03月13日 22:22
  • 1.46MB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:ListView+CheckBox实现全选,全不选功能
举报原因:
原因补充:

(最多只允许输入30个字)