Android开发技巧——自定义单选或多选的ListView
这篇其实应该是属于写自定义单选或多选的ListView的基础教程,无奈目前许多人对此的实现大多都绕了远路,反而使得这正规的写法倒显得有些技巧性了。
本文原创,转载请注明在CSDN上的出处:
http://blog.csdn.net/maosidiaoxian/article/details/45867927
Android中,ListView可以设置choiceMode,可见Android对ListView的单选或多选是有进行封装的,然而我看到的许多单选或多选的ListView,包括我以前写的例子,以前几个老外封装的库,都是自己维护了一个集合,用于存放每个item的选中状态。这样一来,不但代码显得繁复,逻辑上也成冗余,而且容易出BUG。
其实,ListView中,已经自己维护了一个SparseBooleanArray,用于保存每一项的选中状态。而对于每一项,它是通过adapter的getView中获取的view,来设置它的选中状态的。所以,我们需要使得adapter中,getView中返回的这个view实现Checkable接口。下面,将介绍具体实现。
这里介绍的实现方式有两个,一种是从零写一个单选的ListView。另一种是调用我的一个库的代码来实现。因为我已经对相关的必要逻辑都封装在了两个类里,使得易于使用。
原生实现
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_height="wrap_content">
<RadioButton
android:id="@+id/checkedView"
android:layout_centerVertical="true"
android:layout_alignParentLeft="true"
android:clickable="false"
android:focusable="false"
android:focusableInTouchMode="false"
android:layout_width="wrap_content"
android:layout_height="48dp" />
<TextView
android:id="@+id/text"
android:gravity="center_vertical"
android:layout_alignParentRight="true"
android:layout_width="wrap_content"
android:layout_height="48dp" />
</RelativeLayout>
注意,这里的RadioButton,需要设置三个属性,分别是:
android:clickable="false"
android:focusable="false"
android:focusableInTouchMode="false"
2,接下来,继承某个Layout,来实现可以单选的这个item。
package com.githang.android.choicelistview;
import android.content.Context;
import android.view.View;
import android.widget.Checkable;
import android.widget.FrameLayout;
import android.widget.RadioButton;
import android.widget.TextView;
/**
* FIXME
*
* @author Geek_Soledad (msdx.android@qq.com)
*/
public class ChoiceView extends FrameLayout implements Checkable{
private TextView mTextView;
private RadioButton mRadioButton;
public ChoiceView(Context context) {
super(context);
View.inflate(context, R.layout.item_single_choice, this);
mTextView = (TextView) findViewById(R.id.text);
mRadioButton = (RadioButton) findViewById(R.id.checkedView);
}
public void setText(String text) {
mTextView.setText(text);
}
@Override
public void setChecked(boolean checked) {
mRadioButton.setChecked(checked);
}
@Override
public boolean isChecked() {
return mRadioButton.isChecked();
}
@Override
public void toggle() {
mRadioButton.toggle();
}
}
最后,在listview的adapter的getView方法里,返回这个实现了Checkable接口的ChoiceView。
package com.githang.android.choicelistview;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ListAdapter;
import android.widget.ListView;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends ActionBarActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
List<String> data = new ArrayList<>();
for(int i = 0; i < 5; i++) {
data.add("test" + i);
}
ListView listView = (ListView) findViewById(R.id.list_view);
listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
ListAdapter adapter = new ArrayAdapter<String>(this, R.layout.item_single_choice, data) {
@Override
public View getView(int position, View convertView, ViewGroup parent) {
final ChoiceView view;
if(convertView == null) {
view = new ChoiceView(MainActivity.this);
} else {
view = (ChoiceView)convertView;
}
view.setText(getItem(position));
return view;
}
};
listView.setAdapter(adapter);
}
}
代码很简单方便,完全不用自己去维护一个选中状态的集合。Demo 项目下载地址:http://www.400gb.com/file/94898213
使用AndroidSnippet里的类实现
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_height="wrap_content">
<RadioButton
android:id="@+id/checkedView"
android:layout_centerVertical="true"
android:layout_alignParentLeft="true"
android:layout_width="wrap_content"
android:layout_height="48dp" />
<TextView
android:id="@+id/text"
android:gravity="center_vertical"
android:layout_alignParentRight="true"
android:layout_width="wrap_content"
android:layout_height="48dp" />
</RelativeLayout>
关于RadioButton的三个属性我已经在代码里封装好了,所以这里写不写那三个属性都无所谓。
listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
ChoiceListAdapter adapter = new ChoiceListAdapter<String>(this, R.layout.item_single_choice,
data, R.id.checkedView) {
@Override
protected void holdView(ChoiceLayout view) {
view.hold(R.id.text);
}
@Override
protected void bindData(ChoiceLayout view, int position, String data) {
TextView text = view.get(R.id.text);
text.setText(data);
}
};
listView.setAdapter(adapter);
这里的ChoiceLayout 我还对holder进行了封装,用起来是不是更简洁方便?
Android开发技巧——自定义单选或多选的ListView的更多相关文章
- Android开发技巧——使用PopupWindow实现弹出菜单
在本文当中,我将会与大家分享一个封装了PopupWindow实现弹出菜单的类,并说明它的实现与使用. 因对界面的需求,android原生的弹出菜单已不能满足我们的需求,自定义菜单成了我们的唯一选择,在 ...
- Android开发技巧——实现可复用的ActionSheet菜单
在上一篇<Android开发技巧--使用Dialog实现仿QQ的ActionSheet菜单>中,讲了这种菜单的实现过程,接下来将把它改成一个可复用的控件库. 本文原创,转载请注明出处: h ...
- Android开发技巧——自定义控件之增加状态
Android开发技巧--自定义控件之增加状态 题外话 这篇本该是上周四或上周五写的,无奈太久没写博客,前几段把我的兴头都用完了,就一拖再拖,直到今天.不想把这篇拖到下个月,所以还是先硬着头皮写了. ...
- Android开发技巧——自定义控件之使用style
Android开发技巧--自定义控件之使用style 回顾 在上一篇<Android开发技巧--自定义控件之自定义属性>中,我讲到了如何定义属性以及在自定义控件中获取这些属性的值,也提到了 ...
- Android开发技巧——自定义控件之自定义属性
Android开发技巧--自定义控件之自定义属性 掌握自定义控件是很重要的,因为通过自定义控件,能够:解决UI问题,优化布局性能,简化布局代码. 上一篇讲了如何通过xml把几个控件组织起来,并继承某个 ...
- Android开发技巧——自定义控件之组合控件
Android开发技巧--自定义控件之组合控件 我准备在接下来一段时间,写一系列有关Android自定义控件的博客,包括如何进行各种自定义,并分享一下我所知道的其中的技巧,注意点等. 还是那句老话,尽 ...
- Android开发技巧——写一个StepView
在我们的应用开发中,有些业务流程会涉及到多个步骤,或者是多个状态的转化,因此,会需要有相关的设计来展示该业务流程.比如<停车王>应用里的添加车牌的步骤. 通常,我们会把这类控件称为&quo ...
- android开发之自定义组件
android开发之自定义组件 一:自定义组件: 我认为,自定义组件就是android给我们提供的的一个空白的可以编辑的图片,它帮助我们实现的我们想要的界面,也就是通过自定义组件我们可以把我们要登入的 ...
- 50个android开发技巧
50个android开发技巧 http://blog.csdn.net/column/details/androidhacks.html
随机推荐
- python 3 dict函数 神奇的参数规则
>>> dict({1:2},2=3)SyntaxError: keyword can't be an expression>>> dict({1:2},**{2: ...
- 【C++】处理CSDN博文源码
为了简化CSDN写博客的字体问题,给出一段代码,用于处理使用默认格式写完博客后,处理一次来解决字体问题. 代码片段 代码片段如下所示: #include <iostream> #inclu ...
- Android-MVVM架构-Data Binding的使用
项目整体效果: Awesome-Android-MVVM 什么是MVVM, 为什么需要 MVVM? 如何在Android中使用Data Binding实现MVVM架构? 什么是MVVM , 为什么需要 ...
- 迎战大数据-Oracle篇
来自:http://www.cnblogs.com/wenllsz/archive/2012/11/16/2774205.html 了解大数据带来的机遇: 透视架构与工具: 开源节流,获得竞争优势. ...
- UE4 C++与蓝图交互
一.C++调用蓝图的函数 本来应该有一个很好的示例,但一下却忘了适用于哪些地方,只有简单写一个步骤了. 1.新建一个C++类继承Actor,名称随意,我这里继承了一个SplineMesh,一样de,并 ...
- C++对象模型的那些事儿之三:默认构造函数
前言 继前两篇总结了C++对象模型及其内存布局后,我们继续来探索一下C++对象的默认构造函数.对于C++的初学者来说,有如下两个误解: 任何class如果没有定义default constructor ...
- 开源项目——小Q聊天机器人V1.0
小Q聊天机器人V1.0 http://blog.csdn.net/baiyuliang2013/article/details/51386281 小Q聊天机器人V1.1 http://blog.csd ...
- Linux 内存管理之highmem简介
一.Linux内核地址空间 一般来说Linux 内核按照 3:1 的比率来划分虚拟内存(X86等):3 GB 的虚拟内存用于用户空间,1GB 的内存用于内核空间.当然有些体系结构如MIPS使用2:2 ...
- 压力测试工具Ab简介
Apache安装包中自带的压力测试工具 Apache Benchmark(简称ab) 简单易用,这里就采用 ab作为压力测试工具了. 1.独立安装 通过 yum-utils中的yumdownload ...
- javascript 下拉列表 自动取值 无需value
<select id="applyType" name="$!{status.expression}" class="inp" onc ...