Android高级控件(一)——ListView绑定CheckBox实现全选,增加和删除等功能


这个控件还是挺复杂的,也是项目中应该算是比较常用的了,所以写了一个小Demo来讲讲,主要是自定义adapter的用法,加了很多的判断等等等等….我们先来看看实现的效果吧!

好的,我们新建一个项目LvCheckBox

我们事先先把这两个布局写好吧,一个是主布局,还有一个listview的item.xml,相信不用多说

activity_main.xml

<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" >

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:background="#238286" >

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true"
            android:text="ListView绑定CheckBox"
            android:textColor="#fff" />

        <TextView
            android:id="@+id/tv_add"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:layout_centerVertical="true"
            android:layout_marginRight="17dp"
            android:text="增加"
            android:textColor="#fff" />
    </RelativeLayout>

    <ListView
        android:id="@+id/listview"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1" >
    </ListView>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:orientation="horizontal" >

        <Button
            android:id="@+id/btn_detele"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_marginRight="1dp"
            android:layout_weight="1"
            android:background="#238286"
            android:text="删除"
            android:textColor="#fff" />

        <Button
            android:id="@+id/btn_select_all"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_marginLeft="1dp"
            android:layout_weight="1"
            android:background="#238286"
            android:text="全选"
            android:textColor="#fff" />
    </LinearLayout>

</LinearLayout>

item.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="50dp"
    android:gravity="center_vertical"
    android:orientation="horizontal" >

    <TextView
        android:id="@+id/tvTitle"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="15dp"
        android:layout_weight="7"
        android:text="text" />

    <CheckBox
        android:id="@+id/cbCheckBox"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_weight="1" />

</LinearLayout>

item.xml只有两个控件,很好理解吧

初始化控件

我们用initView()方法来初始化这些控件
    private void initView() {
        tv_add = (TextView) findViewById(R.id.tv_add);
        tv_add.setOnClickListener(this);
        btn_detele = (Button) findViewById(R.id.btn_detele);
        btn_detele.setOnClickListener(this);
        btn_select_all = (Button) findViewById(R.id.btn_select_all);
        btn_select_all.setOnClickListener(this);
        listview = (ListView) findViewById(R.id.listview);

    }

然后继承点击事件,button的和listview的

implements OnClickListener,OnItemClickListener

自定义Adapter

这里最难的就是adapter了

1.Bean

我们为了数据的记录方便,我们提前写一个实体类
package com.lgl.lvcheckbox;

public class Bean {

    private String title;

    // 构造方法
    public Bean(String title) {
        super();
        this.title = title;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

}

ListAdapter

这里所有的都写了注释,也方便大家看清
package com.lgl.lvcheckbox;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.TextView;

/**
 * 自定义适配器
 *
 * @author LGL
 *
 */
public class ListAdapter extends BaseAdapter {

    // 数据集
    private List<Bean> list = new ArrayList<Bean>();
    // 上下文
    private Context mContext;
    // 存储勾选框状态的map集合
    private Map<Integer, Boolean> isCheck = new HashMap<Integer, Boolean>();

    // 构造方法
    public ListAdapter(Context mContext) {
        super();
        this.mContext = mContext;
        // 默认为不选中
        initCheck(false);
    }

    // 初始化map集合
    public void initCheck(boolean flag) {
        // map集合的数量和list的数量是一致的
        for (int i = 0; i < list.size(); i++) {
            // 设置默认的显示
            isCheck.put(i, flag);
        }
    }

    // 设置数据
    public void setData(List<Bean> data) {
        this.list = data;
    }

    // 添加数据
    public void addData(Bean bean) {
        // 下标 数据
        list.add(0, bean);
    }

    @Override
    public int getCount() {
        // TODO Auto-generated method stub
        // 如果为null就返回一个0
        return list != null ? list.size() : 0;
    }

    @Override
    public Object getItem(int position) {
        // TODO Auto-generated method stub
        return list.get(position);
    }

    @Override
    public long getItemId(int position) {
        // TODO Auto-generated method stub
        return position;
    }

    @Override
    public View getView(final int position, View convertView, ViewGroup parent) {
        ViewHolder viewHolder = null;
        View view = null;
        // 判断是不是第一次进来
        if (convertView == null) {
            view = LayoutInflater.from(mContext).inflate(R.layout.item, null);
            viewHolder = new ViewHolder();
            viewHolder.title = (TextView) view.findViewById(R.id.tvTitle);
            viewHolder.cbCheckBox = (CheckBox) view
                    .findViewById(R.id.cbCheckBox);
            // 标记,可以复用
            view.setTag(viewHolder);
        } else {
            view = convertView;
            // 直接拿过来用
            viewHolder = (ViewHolder) view.getTag();
        }
        // 拿到对象
        Bean bean = list.get(position);
        // 填充数据
        viewHolder.title.setText(bean.getTitle().toString());
        // 勾选框的点击事件
        viewHolder.cbCheckBox
                .setOnCheckedChangeListener(new OnCheckedChangeListener() {

                    @Override
                    public void onCheckedChanged(CompoundButton buttonView,
                            boolean isChecked) {
                        // 用map集合保存
                        isCheck.put(position, isChecked);
                    }
                });
        // 设置状态
        if (isCheck.get(position) == null) {
            isCheck.put(position, false);
        }
        viewHolder.cbCheckBox.setChecked(isCheck.get(position));
        return view;
    }

    // 优化
    public static class ViewHolder {
        public TextView title;
        public CheckBox cbCheckBox;
    }

    // 全选按钮获取状态
    public Map<Integer, Boolean> getMap() {
        // 返回状态
        return isCheck;
    }

    // 删除一个数据
    public void removeData(int position) {
        list.remove(position);
    }
}

当然,有些方法是后面写的,我们提前写好,比如删除和增加什么的

初始化数据

我们默认总是需要点数据的
    private void initData() {
        // 默认显示的数据
        List<Bean> list = new ArrayList<Bean>();
        list.add(new Bean("张三"));
        list.add(new Bean("李四"));
        list.add(new Bean("王五"));

        adapter = new ListAdapter(this);
        adapter.setData(list);
        listview.setAdapter(adapter);
    }

增加数据

    // 添加数据
        case R.id.tv_add:
            adapter.addData(new Bean("刘桂林"));
            // 通知刷新适配器
            adapter.notifyDataSetChanged();
            break;

全选数据

当我们全选的时候,按钮应该为全不选的,所以这里我们这里有状态的
    case R.id.btn_select_all:
            // 全选——全不选
            Map<Integer, Boolean> isCheck = adapter.getMap();
            if (btn_select_all.getText().equals("全选")) {
                adapter.initCheck(true);
                // 通知刷新适配器
                adapter.notifyDataSetChanged();
                btn_select_all.setText("全不选");
                btn_select_all.setTextColor(Color.YELLOW);
            } else if (btn_select_all.getText().equals("全不选")) {
                adapter.initCheck(false);
                // 通知刷新适配器
                adapter.notifyDataSetChanged();
                btn_select_all.setText("全选");
                btn_select_all.setTextColor(Color.YELLOW);
            }
            break;

删除数据

删除也是要考虑很多因素
// 删除数据
        case R.id.btn_detele:
            // 拿到所有数据
            Map<Integer, Boolean> isCheck_delete = adapter.getMap();
            // 获取到条目数量,map.size = list.size,所以
            int count = adapter.getCount();
            // 遍历
            for (int i = 0; i < count; i++) {
                // 删除有两个map和list都要删除 ,计算方式
                int position = i - (count - adapter.getCount());
                // 判断状态 true为删除
                if (isCheck_delete.get(i) != null && isCheck_delete.get(i)) {
                    // listview删除数据
                    isCheck_delete.remove(i);
                    adapter.removeData(position);
                }
            }
            btn_select_all.setText("全选");
            btn_select_all.setTextColor(Color.WHITE);
            adapter.notifyDataSetChanged();
            break;

这里的

int position = i - (count - adapter.getCount());

是一个计算方式,当我们删除之后,实际上数组是需要重新排列的,同时按钮也要变回全选状态的

listview的点击

我们直接点击也是可以勾选cheakbox选中的
// listview的点击事件
    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position,
            long id) {
        // 判断view是否相同
        if (view.getTag() instanceof ViewHolder) {
            // 如果是的话,重用
            ViewHolder holder = (ViewHolder) view.getTag();
            // 自动触发
            holder.cbCheckBox.toggle();
        }
    }

好的,这样的话就可以实现了,如果不懂的话可以下载本文demo参考,觉得好的点个赞

Demo下载地址:http://download.csdn.net/detail/qq_26787115/9423306

Android高级控件(一)——ListView绑定CheckBox实现全选,增加和删除等功能的更多相关文章

  1. Android高级控件(一)——ListView绑定CheckBox实现全选,添加和删除等功能

    Android高级控件(一)--ListView绑定CheckBox实现全选,添加和删除等功能 这个控件还是挺复杂的.也是项目中应该算是比較经常使用的了,所以写了一个小Demo来讲讲,主要是自己定义a ...

  2. Android高级控件(六)——自定义ListView高仿一个QQ可拖拽列表的实现

    Android高级控件(六)--自定义ListView高仿一个QQ可拖拽列表的实现 我们做一些好友列表或者商品列表的时候,居多的需求可能就是需要列表拖拽了,而我们选择了ListView,也是因为使用L ...

  3. Android 高级控件(七)——RecyclerView的方方面面

    Android 高级控件(七)--RecyclerView的方方面面 RecyclerView出来很长时间了,相信大家都已经比较了解了,这里我把知识梳理一下,其实你把他看成一个升级版的ListView ...

  4. Android高级控件(五)——如何打造一个企业级应用对话列表,以QQ,微信为例

    Android高级控件(五)--如何打造一个企业级应用对话列表,以QQ,微信为例 看标题这么高大上,实际上,还是运用我么拿到listview去扩展,我们讲什么呢,就是研究一下QQ,微信的这种对话列表, ...

  5. Android高级控件(四)——VideoView 实现引导页播放视频欢迎效果,超级简单却十分的炫酷

    Android高级控件(四)--VideoView 实现引导页播放视频欢迎效果,超级简单却十分的炫酷 是不是感觉QQ空间什么的每次新版本更新那炫炫的引导页就特别的激动,哈哈,其实他实现起来真的很简单很 ...

  6. Android高级控件(三)—— 使用Google ZXing实现二维码的扫描和生成相关功能体系

    Android高级控件(三)-- 使用Google ZXing实现二维码的扫描和生成相关功能体系 摘要 现在的二维码可谓是烂大街了,到处都是二维码,什么都是二维码,扫一扫似乎已经流行到习以为常了,今天 ...

  7. Android高级控件(二)——SurfaceView实现GIF动画架包,播放GIF动画,自己实现功能的初体现

    Android高级控件(二)--SurfaceView实现GIF动画架包,播放GIF动画,自己实现功能的初体现 写这个的原因呢,也是因为项目中用到了gif动画,虽然网上有很多的架包可以实现,不过我们还 ...

  8. Android高级控件(三)——&#160;使用Google ZXing实现二维码的扫描和生成相关功能体系

    Android高级控件(三)-- 使用Google ZXing实现二维码的扫描和生成相关功能体系 摘要 如今的二维码可谓是烂大街了.到处都是二维码.什么都是二维码,扫一扫似乎已经流行到习以为常了,今天 ...

  9. Android高级控件--AdapterView与Adapter

    在J2EE中提供过一种非常好的框架--MVC框架,实现原理:数据模型M(Model)存放数据,利用控制器C(Controller)将数据显示在视图V(View)上.在Android中有这样一种高级控件 ...

随机推荐

  1. PullToRefreshScrollView 嵌套RecyclerView实现特卖列表倒计时抢购

    不久之前,我们谈到了通过Handler与timer及TimerTask结合实现倒计时抢购列表,那个是PullToRefreshListView实现的,今天要讲的是PullToRefreshScroll ...

  2. UNIX网络编程——通过UNIX域套接字传递描述符和 sendmsg/recvmsg 函数

    在前面我们介绍了UNIX域套接字编程,更重要的一点是UNIX域套接字可以在同一台主机上各进程之间传递文件描述符. 下面先来看两个函数: #include <sys/types.h> #in ...

  3. Tomcat集群如何同步会话

    Tocmat集群中最重要的交换信息就是会话消息,对某个tomcat实例某会话做的更改要同步到集群其他tomcat实例的该会话对象,这样才能保证集群所有实例的会话数据一致.在tribes组件的基础上完成 ...

  4. Android ListPopupWindow的使用

    其实像ListPopupWindow.PopupMenu的用法大致和PopupWindow的一样!就不讲了,相信用过PopupWindow的看一下就能明白. 先上个效果图: ListPopupWind ...

  5. 通过一个工具类更深入理解动态代理和Threadlocal

    动态代理和Threadlocal 一个代理类返回指定的接口,将方法调用指定的调用处理程序的代理类的实例.返回的是一个代理类,由指定的类装载器的定义和实现指定接口指定代理实例调用处理程序最近用到一个工具 ...

  6. 最近在线笔试的一些感想和总结,阿里巴巴,腾讯,百度,360。c++研发,机器学习等岗位

    持续更新中... 1.编程界牛人太多了,还是要好好a题,好好弄清楚基础算法,并且用代码实现 2.c/c++方向其实来回来去那么几道题,做好了记到脑子里. 下面就是我打算把不会的,不清楚的都贴上来然后好 ...

  7. 【Android 应用开发】 自定义组件 宽高适配方法, 手势监听器操作组件, 回调接口维护策略, 绘制方法分析 -- 基于 WheelView 组件分析自定义组件

    博客地址 : http://blog.csdn.net/shulianghan/article/details/41520569 代码下载 : -- GitHub : https://github.c ...

  8. JavaScript压缩工具JSA使用介绍

    JavaScript压缩工具JSA使用介绍 JSA绝对是我使用过的JS压缩工具中最上乘的一个.认识它是从ligerUI开始.在ligerUI的QQ讨论组里,大神--ligerUI的作者告诉我他的lig ...

  9. OTA和Recovery系统升级流程介绍

    本文介绍了Android原生OTA和Recovery升级过程步骤. 进入升级 - 1.1 正常启动和进入Recovery的区别 下面给出了升级流程的简单示意图.  上图中的上下两个部分,上面一部分是正 ...

  10. [RDLC]一步一步教你使用RDLC(一)

    一:加数据集,并且命名为Quotation,如下图所示: 二: 添加一张报表,命名为Quotation,如下图所示: 向报表中添加"表"这一项,如下图所示: 这时就弹出一个选择数据 ...