ListView多选和单选模式重新整理
超简单的单选和多选ListView
在开发过程中,我们经常会使用ListView去呈现列表数据,比如商品列表,通话记录,联系人列表等等,在一些情况下,我们还需要去选择其中的一些列表数据进行编辑。以前,我在项目开发中,都是在自定义的Adapter中去维护一个SparseBooleanArray变量来保存当前ListView中已经被选中的项,然后在自定义Adapter的getView()和ListView的setOnItemClickListener()方法中去实时更新SparseBooleanArray变量,从而当用户选择提交数据的时候,直接遍历SparseBooleanArray中的值就可以了,这种做法,虽然也能实现功能,但是无疑增加了代码开销。
今天,在看文档的时候,发现了一个更好的解决方案(很多人已经用过了吧):使用ListView的choiceMode,官方文档见如下:

根据上面的文档说明,可以知道,android:choiceMode有以下几个值:默认(不设置android:choiceMode属性,即不支持单选或多选),singleChoice(单选),multipleChoice(多选),mutipleChoiceModal(特殊多选模式,可以通过设置MultiChoiceModeListener进行监听选择模式,类似ActionBar的ActionMode)。在XML中给ListView设置了android:choiceMode属性一个值后,我们还需要给ListView一个适配器,这里我们使用默认的ArrayAdapter:
//如果是单选模式,则可以使用 android.R.layout.simple_list_item_single_choice
ArrayAdapter<String> myAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_multiple_choice, mDatas);
mListView.setAdapter(myAdapter);
这样我们就已经完成了ListView的多选或单选实现。
另外一个问题是:我们怎样才能获取当前ListView中被选中的那些项呢?
我们其实可以通过ListView的isItemChecked(int position)方法判断一项是否被选中,或直接使用ListView.getCheckedItemPositions()来获取所有选中的项,这个方法返回一个SparseBooleanArray对象,遍历它就可以获取所有选中的项。
自定义ListView的多选和单选项布局
对于一些简单的列表,上面的方法可能已经能够满足需求。其实,上面的列表项只显示了一个标题和一个复选框,但在实际开发中,UE或产品经理可能要求我们去实现的列表远比上面的列表复杂得多,所以往往就需要使用自定义的Adapter来填充ListView。
但是,如果我们使用自定义的Adapter来填充ListView,那怎么让我们自定义的Checkbox能够无缝衔接ListView的选择状态呢?
一种普遍的做法是在重写自定义Adapter的getView()时,先通过convertView.findViewById()获取到Checkbox后,通过mList.isItemChecked(int position)判断当前position的状态后,再去更新Checkbox的选择状态。
这里,我介绍的是另外一种方法。
首先,我们先来看下为什么我们使用android.R.layout.simple_list_item_multiple_choice布局来填充ArrayAdapter时,不需要我们自己去维护CheckBox的选择状态?
查看ListView的源码,在ListView的setupChild方法中,有下面的一段代码:
if (mChoiceMode != CHOICE_MODE_NONE && mCheckStates != null) {
if (child instanceof Checkable) {
((Checkable) child).setChecked(mCheckStates.get(position));
} else if (getContext().getApplicationInfo().targetSdkVersion >= android.os.Build.VERSION_CODES.HONEYCOMB)
{
child.setActivated(mCheckStates.get(position));
}
}
即如果ListView的child(从自定义的Adapter的getView()方法中返回的View)实现了Checkable接口,那么当listView的项选择状态改变时,listView也会去同步更新这个child的状态(android 3.1或3.1以上平台,会触发setActivated方法),其实simple_list_item_multiple_choice.xml中只有一个CheckedTextView
<CheckedTextView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@android:id/text1"
android:layout_width="match_parent"
android:layout_height="?android:attr/listPreferredItemHeightSmall"
android:textAppearance="?android:attr/textAppearanceListItemSmall"
android:gravity="center_vertical"
android:checkMark="?android:attr/listChoiceIndicatorMultiple"
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd" />
而CheckedTextView 是实现了Checkable接口的,所以当我们使用simple_list_item_multiple_choic.xml布局作为Adapter的getView()的返回值时,是不需要我们额外去关心Checkbox的状态问题。
通过上面的分析,我们自定义一个View时,只需要实现了Checkable接口,那么就不用我们在getView中去额外维护选中状态了。如果android3.1或android3.1以上的平台,我们还可以重写setActivated方法来更新我们的选中状态。相关示例代码如下:
package com.shaoxiong.li.marvel.myapplication; import android.content.Context;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.CheckBox;
import android.widget.Checkable;
import android.widget.LinearLayout;
import android.widget.TextView; /**
* Created by lishaoxiong on 16-2-22.
*/
public class CustomCheckTextView extends LinearLayout implements Checkable { private TextView titleView;
private CheckBox mCheckBox; public CustomCheckTextView(Context context) {
this(context, null);
} public CustomCheckTextView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
} public CustomCheckTextView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr); LayoutInflater mLayoutInflater = LayoutInflater.from(context);
//将加载出来的View添加到当前View层级中去。
//有两种方案,一种是加载布局时将rootView传进去,或直接使用addView添加进去
//View v = mLayoutInflater.inflate(R.layout.layout_custom_ctv, null);
View v = mLayoutInflater.inflate(R.layout.layout_custom_ctv, this, true);
titleView = (TextView)v.findViewById(R.id.headListView_item_text);
mCheckBox = (CheckBox)v.findViewById(R.id.headListView_item_cb);
//this.addView(v);
} @Override
public void setChecked(boolean checked) {
mCheckBox.setChecked(checked);
} @Override
public boolean isChecked() {
return mCheckBox.isChecked();
} @Override
public void toggle() {
mCheckBox.toggle();
} public void setTitle(String title) {
titleView.setText(title);
} @Override
public void setActivated(boolean activated) {
super.setActivated(activated);
}
}
<?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="match_parent"
android:orientation="horizontal"
android:padding="20dp">
<CheckBox
android:id="@+id/headListView_item_cb"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:focusable="false"
android:clickable="false"
android:focusableInTouchMode="false"/> <TextView
android:id="@+id/headListView_item_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="10dp"/> </LinearLayout>
public class MyAdapter extends BaseAdapter {
private Context mContext;
private ArrayList<String> dataList;
public MyAdapter(Context context, ArrayList<String> dataList) {
this.mContext = context;
this.dataList= dataList;
}
@Override
public int getCount() {
return dataList.size();
}
@Override
public Object getItem(int position) {
return dataList.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder = null;
if(convertView == null) {
convertView = LayoutInflater.from(mContext).inflate(R.layout.item_headlistview, null);
viewHolder = new ViewHolder();
//viewHolder.mTextView = (TextView)convertView.findViewById(R.id.headListView_item_text);
// viewHolder.checkedTv = (CheckedTextView)convertView.findViewById(R.id.item_checked_tv);
viewHolder.customCheckTextView = (CustomCheckTextView)convertView;
convertView.setTag(viewHolder);
}else {
viewHolder = (ViewHolder)convertView.getTag();
}
// viewHolder.checkedTv.setText(dataList.get(position));
// viewHolder.mTextView.setText(dataList.get(position));
viewHolder.customCheckTextView.setTitle(dataList.get(position));
return convertView;
}
}
static class ViewHolder {
// TextView mTextView;
// CheckedTextView checkedTv;
CustomCheckTextView customCheckTextView;
}
这样,通过上面的方法,你就可以去实现各种自己自定义好布局的多选或单选列表了。
ListView多选和单选模式重新整理的更多相关文章
- ListView多选操作模式详解CHOICE_MODE_MULTIPLE与CHOICE_MODE_MULTIPLE_MODAL
这篇文章我们将详细的介绍如何实现ListView的多选操作,文中将会纠正在使用ListViewCHOICE_MODE_MULTIPLE或者CHOICE_MODE_MULTIPLE_MODAL时容易犯的 ...
- ListView多选操作模式——上下文操作模式
1.什么叫上下文操作模式 2.如何进入上下文操作模式 1.ListView自身带了单选.多选模式,可通过listview.setChoiceMode来设置: listview.setChoiceMod ...
- easyui-datagrid单选模式下隐藏表头的全选框
easyui-datagrid可以不使用复选框来进行单选,直接使用onSelect和 singleSelect:true就可以实现单选,但是有一些用户会比较习惯使用勾选框,这时会加一列checkbox ...
- Android实战之ListView复选框
项目中有用到复选框的例子,啊啊......在网上查找有关资料,大多都是过于繁琐,所以自己决定写个这个方面的demo... 先给个效果图: 在ListView中添加复选框主要注意以下几个问题: 1.Li ...
- listview改变选中行字体颜色
[android]listview改变选中行字体颜色 目标:选中item,其字体设置为#3197FF,未选中的,其字体为#FFFFFF 与listvew设置选中行item背景图片一样,使用select ...
- 【android】listview改变选中行背景图片
[android]listview改变选中行背景图片 目标:当item选中时,改变其背景图片.效果图如下: 直接在listview的xml文件中使用listselector: 1 2 3 4 5 6 ...
- jq pagination分页 全选、单选的思考
$().pagination(总条数,配置项); 后端分页的跨页选择: 思路:把浏览过的页整体保存为,整体拥有 curPage(当前页码).allChoice(当前页是否全选).selected当前页 ...
- [CSS]复选框单选框与文字对齐问题的研究与解决.
前言:今天碰到的这个问题, 恰好找到一个很好的博文, 在这里转载过来 学习下. 原文地址:复选框单选框与文字对齐问题的研究与解决. 目前中文网站上面的文字,就我的个人感觉而言,绝大多数网站的主流文字大 ...
- ylbtech-数据库设计与优化-对作为复选框/单选列表的集合表的设计
ylbtech-DatabaseDesgin:ylbtech-数据库设计与优化-对作为复选框/单选列表的集合表的设计 -- DatabaseName:通用表结构-- -- 主要是针对将要设计的表对象, ...
随机推荐
- 解决unknown import path "golang.org/x/sys/unix": unrecognized import path "golang.org/x/sys"
问题描述 当我们使用 go get.go install.go mod 等命令时,会自动下载相应的包或依赖包.但由于众所周知的原因,类似于 golang.org/x/... 的包会出现下载失败的情况. ...
- 在windows搭建jenkins測试环境
jenkins 搭建好开发环境必备之中的一个,简单易用,搭建測试平台非常有帮助,不知道的都能够了解一下 官网下载地址 http://jenkins-ci.org/ 我是下载window版本号的 安装有 ...
- 【ActionScript】Flash与网页的交互,ActionScript与JavaScript的交互
Flash是可以轻松与网页交互数据的,不然为何Flash会有这么大的生命力呢?仅仅是这样编程比較麻烦而已,又要调试Flash,然后又要放到server上调试. 只是这种方式可以收到非常好的效果.Fla ...
- 拿wordpress站的一个小技巧
记得09年时wp爆过一个重置管理口令的漏洞, 现在用法差不多, 也是我刚刚发现, 网上也没找到有讲述关于这个的. 前提:是在有注入点(注入点的话可以通过寻找插件漏洞获得.), 密码解不开, 无法out ...
- Chrome 插件 CrxMouse 去除后门优化版
说明 CrxMouse 是一款挺不错的 Chrome 插件.仅仅是据说这个插件会在后台偷偷的上传用户的浏览数据,无论上传的内容是不是涉及隐私数据,总让人认为不放心,可是因为插件本身功能还是挺好用的,所 ...
- Controller跳转到外部链接
return new ModelAndView(new RedirectView("http://www.baidu.com")); 用了这个方法之后,方法的返回值也会变成mode ...
- Centos6.0使用第三方YUM源(EPEL,RPMForge,RPMFusion)
yum是centos下很方便的rpm包管理工具,配置第三方软件库使你的软件库更加丰富.以下简单的讲下配置的步骤. 首先,需要安装yum-priorities插件: yum install yum-pr ...
- HTML5 手机网页制作笔记
http://top.css88.com/archives/546 http://www.w3cfuns.com/blog-5470280-5406828.html 最近在卓手机网页,第一次入手.把要 ...
- 关于cocos2d-x 和安卓之间的相互调用
近期在研究cocos2d游戏移植安卓须要调用非常多方法.所以在研究之中写下它们之间相互调用 首先,cocos2d调用安卓 在一个.h文件里加入头文件 #include <jni.h> #i ...
- HTML5开发移动web应用——SAP UI5篇(8)
本次对之前学习的SAP UI5框架知识进行简单小结.以及重点部分知识的梳理. 1.在UI5使用过程中,命名空间的概念非常重要. 2.一般的sap组件引用格式例如以下: sap.ui.define([ ...