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
随机推荐
- ORACLE异常(整理网上资料)
一.oracle预定义异常 命名的系统异常 产生原因 Oracle Error SQLCODE Value ACCESS_INTO_NULL 未定义对象 ORA-06530 -6530 CASE_N ...
- 熟悉java语言的基本使用:简单存款取款机制java实现
最近一直没有项目做,于是我也不能这样闲着,我得开始学习新的技术,并且巩固以前自学的技术.以下就是我写的一个简单的java存取款代码,很简单,可能还有更简单的方法,目的是为了熟悉java的基本使用. p ...
- 自定义AlertDialog(仿微信)
安卓自定义AlertDialog,原理很简单: AlertDialog dialog = new AlertDialog.Builder(MainActivity.this).create(); di ...
- 发运模块中如何创建Debug 文件
版本11.5.9到12.x A. 针对发运事务处理或者快速发运产生Debug文件 注意:如果通过发运事务处理执行发放,请参考B部分,下面这部分销售订单发放是格外的设置和日志文件. 1. 每一 ...
- Android的AdapterViewFlipper和Stackview-android学习之旅(三十)
AdapterViewFlipper简介 AdapterViewFlipper继承了AdapterViewAnimater.每次只能显示一个组件,用showPrevious()和showNext()来 ...
- 从Eclipse插件中读取资源
可以通过Eclipse里的OSGi的Bundle类,获取插件目录下的某个文件的输入流: 1. Bundle bundle = Platform.getBundle(Activator.PLUGIN_I ...
- [Mac] mac linux 多线程下载利器 axel
> 之前做过一些文件下载的统计,发现谷歌浏览器chrome和火狐firefox, 一般都是单线程的下载文件,360浏览器却是多线程的下载. 现在切换到了mac上,发现没有360哪个浏览器,就像 ...
- Linux下利用ssh远程文件传输 传输命令 scp
在linux下一般用scp这个命令来通过ssh传输文件. 一.scp是什么? scp是secure copy的简写,用于在Linux下进行远程拷贝文件的命令,和它类似的命令有cp,不过cp只是在本机进 ...
- mxgraph进阶(二)mxgraph的初步介绍与开发入门
mxgraph的初步介绍与开发入门 前言 由于小论文实验需求,需要实现根据用户日志提取出行为序列,然后根据行为序列生成有向图的形式,并且连接相邻动作的弧上标有执行此次相邻动作的频次.为此,在大师兄徐凯 ...
- 【一天一道LeetCode】#94. Binary Tree Inorder Traversal
一天一道LeetCode 本系列文章已全部上传至我的github,地址:ZeeCoder's Github 欢迎大家关注我的新浪微博,我的新浪微博 欢迎转载,转载请注明出处 (一)题目 Given a ...