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:通用表结构-- -- 主要是针对将要设计的表对象, ...
随机推荐
- 算法之美--1.蒙特卡洛方法计算pi
基本思想: 利用圆与其外接正方形面积之比为pi/4的关系,通过产生大量均匀分布的二维点,计算落在单位圆和单位正方形的数量之比再乘以4便得到pi的近似值.样本点越多,计算出的数据将会越接近真识的pi(前 ...
- 【京东账户】——Mysql/PHP/Ajax爬坑之购物车列表分页
一.引言 做京东账户项目中的购物车模块,功能之四就是购物车列表的分页显示.要用到的是Apach环境,Mysql.PHP以及Ajax. 二.查询数据 mysql: SELECT * FROM jd_pr ...
- T4模板编辑器
一 二.工具 (T4模板编辑器) 使用效果 1.tangibleT4EditorPlusModellingToolsVS2013.msi 2.devart T4 Editor for Visual ...
- API接口管理工具postman等
国外 postman Swagger:国外比较流行的一款管理工具,英文配置,需要一定的英文基础和服务器搭建基础,学习成本较高. 国内 Apizza: 风格类似postman,熟悉postman的会比较 ...
- Redis 在 Java 中的使用
转:http://blog.csdn.net/jiangtao_st/article/details/8256610 一.下载jar包 https://github.com/xetorthio/jed ...
- wordpress账户防暴力破解攻击
一.修改数据库表前缀 默认的表前缀是wp_,如果你安装博客的时候没有修改,可以参考这篇文章修改下表前缀. 修改完登录测试下,如果登录成功后提示“您没有足够的权限访问该页面”,说明前缀没有修改完整,参照 ...
- ext tree展开时的一些技巧
加入子节点的时候.我们须要展开父节点.并选中刚加入好的节点. 这时候会有一个问题. 我用的ext-js-4.2起码有一种问题. 节点内部会混乱.要么多加一个. 要么层级会发生故障. 随后我发现一个窍门 ...
- Linux下MySQL定时按日期备份数据
一.使用mysql内置命令 mysqldump Usage: mysqldump [OPTIONS] database [tables] mysqldump [OPTIONS] --databases ...
- Nginx绑定多个域名的方法
nginx绑定多个域名可又把多个域名规则写一个配置文件里,也可又分别建立多个域名配置文件,我一般为了管理方便,每个域名建一个文件,有些同类域名也可又写在一个总的配置文件里. 一.每个域名一个 ...
- linux安装svn客户端subversion及使用方法
1.下载 [maintain@HM16-213 software]$ wget http://subversion.tigris.org/downloads/subversion-deps-1.6.1 ...