自定义单选或多选的ListView

这篇其实应该是属于写自定义单选或多选的ListView的基础教程,无奈目前许多人对此的实现大多都绕了远路,反而使得这正规的写法倒显得有些技巧性了。

本文原创,转载请注明在CSDN上的出处:

Android中,ListView可以设置choiceMode,可见Android对ListView的单选或多选是有进行封装的,然而我看到的许多单选或多选的ListView,包括我以前写的例子,以前几个老外封装的库,都是自己维护了一个集合,用于存放每个item的选中状态。这样一来,不但代码显得繁复,,逻辑上也成冗余,而且容易出BUG。

其实,ListView中,已经自己维护了一个SparseBooleanArray,用于保存每一项的选中状态。而对于每一项,它是通过adapter的getView中获取的view,来设置它的选中状态的。所以,我们需要使得adapter中,getView中返回的这个view实现Checkable接口。下面,将介绍具体实现。

这里介绍的实现方式有两个,一种是从零写一个单选的ListView。另一种是调用我的一个库的代码来实现。因为我已经对相关的必要逻辑都封装在了两个类里,使得易于使用。

原生实现

1,先写item的布局文件。

<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android=""android:layout_width="match_parent" android:layout_height="wrap_content"><RadioButtonandroid: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" /><TextViewandroid: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);}@Overridepublic void setChecked(boolean checked) {mRadioButton.setChecked(checked);}@Overridepublic boolean isChecked() {return mRadioButton.isChecked();}@Overridepublic 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 {@Overrideprotected 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) {@Overridepublic 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 项目下载地址:

使用AndroidSnippet里的类实现

接下来还有更简单的实现方法,即使用我封装的类来实现。这种情况下,只需要写一个item的布局文件,然后写一个adapter即可,和写普通的ListView没多大区别。

item 的布局文件:

<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android=""android:layout_width="match_parent" android:layout_height="wrap_content"><RadioButtonandroid:id="@+id/checkedView"android:layout_centerVertical="true"android:layout_alignParentLeft="true"android:layout_width="wrap_content"android:layout_height="48dp" /><TextViewandroid:id="@+id/text"android:gravity="center_vertical"android:layout_alignParentRight="true"android:layout_width="wrap_content"android:layout_height="48dp" /></RelativeLayout>关于RadioButton的三个属性我已经在代码里封装好了,所以这里写不写那三个属性都无所谓。

接下来,就是使用我封装的ChoiceListAdapter,来实现单选(或多选)的ListView,代码如下:

你说只有有缘人才可以取下,我看着你手中的戒指,

自定义单选或多选的ListView

相关文章:

你感兴趣的文章:

标签云: