【转】带checkbox的ListView实现(二)——自定义Checkable控件的实现方法
原文网址:http://blog.csdn.net/harvic880925/article/details/40475367
前言:前一篇文章给大家展示了传统的Listview的写法,但有的时候我们并不想在DataHolder类中加一个标识是否选中的checked的成员变量,因为在项目开发中,大部分的ListItemLayout布局都是大家共用的,有些人根本不需要checkbox控件,所以会在初始化的时候把这个控件给隐藏掉,但我们的DataHolder在构造的时候以及ListItemAdapter在渲染的时候都需要checked变量,这就有点坑了,所以要想办法能让checkbox不与数据相关联,可能我说到这大家都不大明白我在说什么,其实我也感觉我没讲明白,没关系,往下看,等这篇文章看完之后,如果还没明白,那就给我留言吧。
相关文章:
1、《带checkbox的ListView实现(一)——数据与渲染完全分离的传统实现方式》
2、《带checkbox的ListView实现(二)——自定义Checkable控件的实现方法》
3、《带checkbox的ListView实现(三)——CheckableImageView的实现方法》
同样,还是先给大家看看效果图:(与上篇的效果一样,其实我就是用的上一篇的效果图
)
同样,我们还是从布局开始讲。
一、activity_main.xml ——MainActivity布局文件
- <FrameLayout 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"
- tools:context="com.harvic.trylistviewcheckbox.MainActivity" >
- <ListView
- android:id="@+id/list"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginBottom="100dp"
- android:choiceMode="multipleChoice"
- android:dividerHeight="1px"
- android:scrollbars="none" />
- <Button android:id="@+id/all_sel"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:layout_marginBottom="50dip"
- android:layout_gravity="bottom"
- android:text="全选"
- />
- <Button android:id="@+id/all_unsel"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:layout_gravity="bottom"
- android:text="全部取消"/>
- </FrameLayout>
注意啦:
这里的布局是与上一篇一样一样的,一个ListView两个按钮。但这里有个参数必须要添加:
在ListView中:
- android:choiceMode="multipleChoice"
这个很重要,android:choiceMode中有三个取值:none、singleChoice、multipleChoice;分别代表:不可选择,单选和多选。在这里,不同的取值对ListView的影响是不一样的,但这个影响仅对ListView的Item自己带有checkable属性时才起作用,对于没有checkable属性的ListView是没有任何效果的,比如,你把android:choiceMode这个参数放在上篇的代码中,无论你取什么值都没有任何作用,具体为什么,下面再讲。
二、check_list_item.xml —— 单个Item布局
- <?xml version="1.0" encoding="utf-8"?>
- <com.harvic.trylistviewcheckbox.CheckableFrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="68dp">
- <CheckBox
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="right|center_vertical"
- android:button="@drawable/checkbox_selector"
- android:clickable="false"
- android:focusable="false" />
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_marginBottom="17dp"
- android:layout_marginTop="17dp"
- android:orientation="vertical">
- <TextView
- android:id="@+id/title"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textSize="16sp" />
- <TextView
- android:id="@+id/subtitle"
- android:textSize="12sp"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content" />
- </LinearLayout>
- </com.harvic.trylistviewcheckbox.CheckableFrameLayout>
这里与上一篇有两个地方不同:
1、很明显,使用的自定义控件CheckableFrameLayout;
2、CheckBox控件没有定义ID值,如果根据上一篇的方式,大家可能会打个问号,没有ID怎么获取这个控件,又怎么让它显示选中与不选中呢。
下面看看自定义的控件类CheckableFrameLayout的实现:
- package com.harvic.trylistviewcheckbox;
- import android.content.Context;
- import android.util.AttributeSet;
- import android.view.View;
- import android.widget.Checkable;
- import android.widget.FrameLayout;
- public class CheckableFrameLayout extends FrameLayout implements Checkable {
- public CheckableFrameLayout(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
- private boolean mChecked = false;
- @Override
- public void toggle() {
- setChecked(!mChecked);
- }
- @Override
- public boolean isChecked() {
- return mChecked;
- }
- @Override
- public void setChecked(boolean checked) {
- if (mChecked != checked) {
- mChecked = checked;
- refreshDrawableState();
- for (int i = 0, len = getChildCount(); i < len; i++) {
- View child = getChildAt(i);
- if(child instanceof Checkable){
- ((Checkable) child).setChecked(checked);
- }
- }
- }
- }
- }
因为我们用到的是FrameLayout控件,所以这里派生自FrameLayout,如果用到诸如LinearLayout,RelativeLayout控件等,就要改成对应的类。最后还继承了Checkable接口;
FrameLayout没什么好讲的,就是帧布局。关键问题在于Checkable接口,凡实现这个接口的控件都将具有可选中状态的属性;在普通控件中,具有这个状态的有:CheckBox, CheckedTextView, CompoundButton, RadioButton, ToggleButton等。(《Android 中文API (33) —— Checkable》)对于如何展示它的选中状态需要用户自主实现三个函数:isChecked(),toggle(),setChecked();也就是说,当用户使用ListView.setItemChecked(int position,bool checked)函数来将指定的Item设为Checked标识时,就会自动调用这里的SetChecked()函数。在代码中,我们如何设计,用户界面就会显示怎样的选中状态;
把SetChecked()函数单独拿出来看看:
- public void setChecked(boolean checked) {
- if (mChecked != checked) {
- mChecked = checked;
- refreshDrawableState();
- for (int i = 0, len = getChildCount(); i < len; i++) {
- View child = getChildAt(i);
- if(child instanceof Checkable){
- ((Checkable) child).setChecked(checked);
- }
- }
- }
- }
由于CheckableFrameLayout在ListItem的布局中有三个控件,两个TextView和一个checkbox;所以当用户设置点击属性时,我们要将CheckableFrameLayout的子控件checkbox根据传进来的checked参数更改当前的状态,所以对它下面的所有子控件进行轮循,因为checkbox是具有checkable属性的,所以如果此控件具有checkable属性说明肯定会checkbox,就将它设置为用户指定的checked状态;
三、ViewHolder——ListItem对应的视图类
- public class ViewHolder{
- public TextView mTitle;
- public TextView mSubTitile;
- };
注意,这里没有了checkbox控件所对应的mCheckBox对象;
四、DataHolder——ListItem对应的数据类
- package com.harvic.trylistviewcheckboxdata;
- public class DataHolder{
- public String titleStr;
- public String subTitleStr;
- public DataHolder(String title,String subTitle){
- titleStr = title;
- subTitleStr = subTitle;
- }
- }
同样,这里有标识主标题文字的titleStr和标识副标题的subTitleStr;但没有了标识选中状态的checked变量,因为我们的控件选中的处理是listviewItem自己完成的。
五、ListItemAdapter
- package com.harvic.trylistviewcheckbox;
- import java.util.List;
- import com.example.trylistviewcheckbox.R;
- import android.content.Context;
- import android.view.LayoutInflater;
- import android.view.View;
- import android.view.ViewGroup;
- import android.widget.BaseAdapter;
- import android.widget.TextView;
- public class ListitemAdapter extends BaseAdapter {
- private List<DataHolder> mList;
- private Context mContext;
- private LayoutInflater mInflater;
- public ListitemAdapter(Context context,List<DataHolder> list){
- mList = list;
- mContext = context;
- mInflater = LayoutInflater.from(context);
- }
- @Override
- public int getCount() {
- // TODO Auto-generated method stub
- return mList.size();
- }
- @Override
- public Object getItem(int position) {
- // TODO Auto-generated method stub
- return mList.get(position);
- }
- @Override
- public long getItemId(int position) {
- // TODO Auto-generated method stub
- return position;
- }
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- // TODO Auto-generated method stub
- ViewHolder holder = null;
- if (convertView == null) {
- holder=new ViewHolder();
- convertView = mInflater.inflate(R.layout.check_list_item, null);
- holder.mTitle = (TextView)convertView.findViewById(R.id.title);
- holder.mSubTitile = (TextView)convertView.findViewById(R.id.subtitle);
- convertView.setTag(holder);
- }else {
- holder = (ViewHolder)convertView.getTag();
- }
- holder.mTitle.setText((String)mList.get(position).titleStr);
- holder.mSubTitile.setText((String)mList.get(position).subTitleStr);
- return convertView;
- }
- }
在渲染等等上基本一样,唯一不同之处在于没有了对checkbox控件的处理。
六、 MainActivity
先看看MainActivity的全部代码,然后慢慢讲。
- package com.harvic.trylistviewcheckbox;
- import java.util.ArrayList;
- import java.util.List;
- import com.example.trylistviewcheckbox.R;
- import android.app.Activity;
- import android.os.Bundle;
- import android.view.Menu;
- import android.view.MenuItem;
- import android.view.View;
- import android.widget.Button;
- import android.widget.ListView;
- public class MainActivity extends Activity {
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- //构造数据
- final List<DataHolder> dataList = new ArrayList<DataHolder>();
- for(int i=0;i<10;i++){
- dataList.add(new DataHolder("harvic的blog------"+i,"harvic"));
- }
- //构造Adapter
- ListitemAdapter adapter = new ListitemAdapter(MainActivity.this, dataList);
- final ListView listView = (ListView)findViewById(R.id.list);
- listView.setAdapter(adapter);
- //全部选中按钮的处理
- Button all_sel = (Button)findViewById(R.id.all_sel);
- Button all_unsel = (Button)findViewById(R.id.all_unsel);
- all_sel.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- // TODO Auto-generated method stub
- for(int i=0;i<dataList.size();i++){
- listView.setItemChecked(i, true);
- }
- }
- });
- //全部取消按钮处理
- all_unsel.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- // TODO Auto-generated method stub
- for(int i=0;i<dataList.size();i++){
- listView.setItemChecked(i, false);
- }
- }
- });
- }
- }
先看一下处理步骤:构造数据-》构造Adapter并设置
但!但!但!没有listView.setOnItemClickListener()的设置!!!!!!!!!!!
到这里大家可能要疑问了,为什么没有设计ItemClick的设置,它依然能处理checkbox的事件响应呢?当然是因为我们前面让自定义的CheckableFrameLayout具有了标识可以选中状态的Checkable接口,所以ListView的每一个Item现在都具有Checkbox的点击属性,换句话说,我们的CheckableFrameLayout其实就是扩展的Checkbox控件!当然也可以对ListView设置OnItemClick事件监听,用以处理Item项点击事件;
再看看全选按钮的实现:
- all_sel.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- // TODO Auto-generated method stub
- for(int i=0;i<dataList.size();i++){
- listView.setItemChecked(i, true);
- }
- }
- });
因为我们的每个ListViewItem都具有Checkable属性,所以调用ListView的setItemChecked()函数是有作用的,如果我们的ListviewItem不具有Checkable属性,那么无论你怎么调用SetItemChecked函数都不会起什么效果!
全部取消也很简单了,同样是轮循所有的Item,然后把利用SetItemChecked(i,false)即可。
七、附:获取所有选中行的行号
上面,我们基本实现了自定义控件实现自动选中checkbox的功能,但有时,我们在选中后,更需要知道,我们都选中了哪些,下面的代码就实现了这个功能:其中position就是获取到了当前选中行的position
- SparseBooleanArray checkedArray = mListView.getCheckedItemPositions();
- for (int i = 0; i < checkedArray.size(); i++) {
- if (checkedArray.valueAt(i)){
- ……//i就是选中的行号
- }
- }
OK啦 ,到这就全部讲完了,对于自定义控件的这部分涉及的到东东比较多,不知道大家理解的怎么样,如果有哪部分没理解的话,在评论中回复下,我再修改内容。或许能直接给出应该怎么组织本文的建议就更好不过了,谢谢。
如果本文有帮到你,记得加关注哦!
源码下载地址:http://download.csdn.net/detail/harvic880925/8083133
请大家尊重原创者版权,转载请标明出处哦:http://blog.csdn.net/harvic880925/article/details/40475367 谢谢!
版权声明:本文为博主原创文章,未经博主允许不得转载。
【转】带checkbox的ListView实现(二)——自定义Checkable控件的实现方法的更多相关文章
- arcgis api for js共享干货系列之二自定义Navigation控件样式风格
arcgis api for js默认的Navigation控件样式风格如下图: 这样的风格不能说不好,各有各的爱好,审美观,这里也不是重点,这里的重点是如何自定义一套自己喜欢的样式风格呢:自己自定义 ...
- arcgis api 3.x for js 共享干货系列之二自定义 Navigation 控件样式风格(附源码下载)
0.内容概览 自定义 Navigation 控件样式风格 源码下载 1.内容讲解 arcgis api 3.x for js 默认的Navigation控件样式风格如下图:这样的风格不能说不好,各有各 ...
- Xamarin.forms 自定义tabview控件
一 问题描述 forms本身ui代码是翻译为平台原生代码,forms按照xaml技术进行对android和ios两种ui模型进行公共抽象出了几种page和view,在空杯博客已经有详细介绍 http: ...
- Android自定义用户控件简单范例(二)
对于完全由后台定制的控件,并不是很方便其他人的使用,因为我们常常需要看到控件放到xml界面上的效果,并根据效果进行布局的调整,这就需要一个更加标准的控件制作流程: 我们的自定义控件和其他的控件一样,应 ...
- 自定义组合控件,适配器原理-Day31
自定义组合控件,适配器原理-Day31 mobile2.1 主页定义 手机上锁功能 1.弹出设置密码框. 手机下载进度 自定定义控件 控件的属性其实就是控件类一个属性设置属性调用类的set方法方法, ...
- iOS开发UI篇—Quartz2D(自定义UIImageView控件)
iOS开发UI篇—Quartz2D(自定义UIImageView控件) 一.实现思路 Quartz2D最大的用途在于自定义View(自定义UI控件),当系统的View不能满足我们使用需求的时候,自定义 ...
- WPF: 实现带全选复选框的列表控件
本文将说明如何创建一个带全选复选框的列表控件.其效果如下图: 这个控件是由一个复选框(CheckBox)与一个 ListView 组合而成.它的操作逻辑: 当选中“全选”时,列表中所有的项目都 ...
- 【Android开发日记】之入门篇(十四)——Button控件+自定义Button控件
好久不见,又是一个新的学期开始了,为什么我感觉好惆怅啊!这一周也发生了不少事情,节假日放了三天的假(好久没有这么悠闲过了),实习公司那边被组长半强制性的要求去解决一个后台登陆的问题,结果就是把 ...
- WPF实现带全选复选框的列表控件
本文将说明如何创建一个带全选复选框的列表控件.其效果如下图: 这个控件是由一个复选框(CheckBox)与一个 ListView 组合而成.它的操作逻辑: 当选中“全选”时,列表中所有的项目都会被选中 ...
随机推荐
- Junit使用教程(一)
几乎所有程序员都听说过Junit的大名,但不知真正懂得运用它的人有多少,我便是其中的一个小白. 知道Junit是用来测试的,但却把“宝刀”当成了“菜刀”用.为了从此不再菜鸟,特此总结整理了下Junit ...
- iOS异步图片加载优化与常用开源库分析
网络图片显示大体步骤: 1.下载图片: 2.图片处理(裁剪,边框等): 3.写入磁盘: 4.从磁盘读取数据到内核缓冲区: 5.从内核缓冲区复制到用户空间(内存级别拷贝): 6.解压缩为位图(耗cpu较 ...
- Android(java)学习笔记244:多媒体之SurfaceView
1. SurfaceView: 完成单位时间内界面的快速切换(游戏界面流畅感). 我们之前知道一般的View,只能在主线程里面显示,主线程中更新UI.但是SurfaceView可以在子线程中里 ...
- 使用MWC四轴起飞侧翻解决方法
原因如下:1.电机顺序错了,如上图所示,上面蓝色的箭头是机头,绿色的箭头是电机转向,3.10.11.9对应MWC飞控版上的D3,D9,D11,D9,蓝色箭头对应MWC飞控板的箭头 或者传感器的Y轴 以 ...
- oracle 自治事物 -- autonomous transaction
一 使用规则 : 在begin 之前申明 : PRAGMA AUTONOMOUS_TRANSACTION; 二 使用理解:autonomous transaction 是一个独立的事务,这一点是理解 ...
- springmvc的几点见解
@Controller //标注在Bean的类定义处 @RequestMapping //可以标注在类定义处,将Controller和特定请求关联起来. //可以标注在方法签名处,以便进一步对请求进行 ...
- Oracle NULLIF函数
Oracle NULLIF函数 Oracle NULLIF函数语法为NULLIF(表达式1,表达式2),如果表达式1和表达式2相等则返回空值,如果表达式1和表达式2不相等则返回表达式1的结果. 注意: ...
- 【转】iOS开发系列--数据存取
原文: http://www.cnblogs.com/kenshincui/p/4077833.html#SQLite 概览 在iOS开发中数据存储的方式可以归纳为两类:一类是存储为文件,另一类是存储 ...
- 【USACO 1.5.1】数字金字塔
[题目描述] 观察下面的数字金字塔. 写一个程序来查找从最高点到底部任意处结束的路径,使路径经过数字的和最大.每一步可以走到左下方的点也可以到达右下方的点. 7 3 8 8 1 0 2 7 4 4 4 ...
- Java中的继承与组合
本文主要说明Java中继承与组合的概念,以及它们之间的联系与区别.首先文章会给出一小段代码示例,用于展示到底什么是继承.然后演示如何通过“组合”来改进这种继承的设计机制.最后总结这两者的应用场景,即到 ...