Adapter实现ListView带多选框等状态的自定义控件的注意事项

Android本身为ListView提供了几个方便的Adapter,比如ArrayAdapter、SimpleCurrentAdapter等等。但是为了实现更复杂的列表视图和控制,一般都要继承BaseAdapter来实现自己的Adapter。

我需要的ListView是如图一样的实现SD卡资源文件浏览列表,每个列表项由一个ImageView、TextView、CheckBox组成,并且要求当整个列表中有一个或一个以上的Checkbox被选中时,右上角的搜索按钮就显示出来,否则就隐藏,因此需要对每个列表项的CheckBox设置监听器。若使用Android提供的Adapter实现起来比较复杂,所以我选择继承BaseAdapter来实现自己的Adapter。

首先要知道的是ListView显示原理。ListView接收了Adapter之后,ListView的列表项数据是来源于接收的Adapter的。当ListView要展现出来的时候,ListView就会调用Adapter的getCount方法来获得一共需要绘制多少个列表项,之后就开始调用getView方法来获得每个列表项的View进行装载。也就是说ListView的列表项就是每次调用getView返回的View,每次调用getView获得的列表项View是什么样子,我们看到的这个列表项就是什么样子。

我继承BaseAdapter来实现自己的Adapter,至少需要重写基本的getView、getCount、getItem、getItemID四个方法。其中getCount和getView的功能如上所述,所以我要想实现对每个列表项多选框按钮的监听就需要在getView中返回View给ListView之前,对View中的多选框设置监听器。getView方法中带三个参数public View getView(int position,View convertView,ViewGroup parent),一般都是将convertView最为返回的View。

在这里,需要插播说明一下Android系统对ListView的实现小细节。Android构造ListView列表项的时候每次只会构造足够满足屏幕显示数量的列表项,一般都是10个左右。当ListView的列表项多于屏幕能够显示的列表项的时候,ListView就可以上下拉动,每次拉动显示后续列表项时就会再次调用getView方法来构造后续列表项的View。如果ListView是首次显示出来,那么getView的参数View convertView就是null空的;如果是拉动ListView调用的getView,那么这时getView的参数convertView就不再是null,而是随着拉动刚刚被拉走隐藏掉的列表项的View。这么做的好处是可以节省资源。

基于这个细节,如果重写getView方法时,要将参数convertView作为返回View,那么getView中就应该判断convertView是否为null。为空的话就需要使用Inflater构造出来,不为空的话就可以直接使用了。我的需求中需要对多选框进行监听,所以在返回convertView之前需要中convertView中获取多选框控件并设置监听器。

一开始,我以为这样就能够实现我的需求了,但是出来的结果却意想不到。当我点击一个多选框后,将列表往下拉,下面出来的没有选中的列表框也变成选中的状态。注意到我每次点击一个多选框后往下拉同步被选中的多选框的距离都是不变的,总是相隔11项。于是,回想getView中convertView参数的特点,当我往下拉的时候,ListView调用getView方法中的convertView就是回收来的因为拉动被隐藏的View。在我这个例子中,由于多选框是一种带有状态标示的控件,我的getView没有对其状态进行重新设置,所以就造成了这种奇怪现象。我的解决方法是在我实现的Adapter类中创建一个boolean数组用于保存对应列表项多选框的状态(getView中第一个参数position就是列表项ID,是根据数据来标识,不是根据列表项View来标识的,所以可以根据position来对列表项数据进行选中和非选中标识),每次调用getView都会在其中判断position位置上的boolean值来决定多选框的状态。

同样的,基于这个原理,使用其它带状态的控件也需要注意getView回收的问题。当然,也可以不使用convertView最为getView的返回结果,而在getView每次调用都重新构造一个View,或者Adapter类中构造一个与数据数量等长的View数组。不过这么做的话就比较消耗资源。

另外,BaseAdapter中的getItem和getItemId方法再构造ListView构造过程中并没有使用过,不过据说是在关于ListView的一些监听器中会调用到,所以继承BaseAdapter时最好也给这两个方法返回一个有意义的值。getItemId一般返回对应的position,getItem返回对应position的列表数据对象。

(0)

相关推荐

  • Android ListView适配器(Adapter)优化方法详解

    Android ListView的优化,在做Android项目的时候,在用到ListView 界面及数据显示,这个时候如果资源过大,对项目来说,用户体验肯定是不好的,这里就对如何优化做了详细介绍: Adapter的作用就是ListView界面与数据之间的桥梁,当列表里的每一项显示到页面时,都会调用Adapter的getView方法返回一个View.想过没有? 在我们的列表有1000000项时会是什么样的?是不是会占用极大的系统资源? ListView的Adapter的作用如下图所示: 先看看下面

  • Android开发中ListView自定义adapter的封装

    [引入] 我们一般编写listView的时候顺序是这样的:  •需要展示的数据集List<T>  •为这个数据集编写一个ListView  •为这个ListView编写一个Adapter,一般继承自BaseAdapter  •在BaseAdapter内部编写一个ViewHolder类,对应ListView里面的item控件,提高控件的查询效率 分析: List<T>:ListView --> Adapter extends BaseAdapter --> ViewHol

  • ListView的Adapter使用 之 初学ArrayAdapter String

    ListView是Android中经常会使用的东西,绑定数据对于初学者来说,尤其是刚接触编程的人来说,往往会觉得很难理解,我上大二的时候学的java,但是基本上相当于没有学,什么都没写过,真正接触编程就是开始上手学android,把这些记录下来,自己可以回头看下,也可以让新手更好的理解.高手绕过.... Android中Adapter我是这么理解的,是数据和视图之间的桥梁,数据在adapter中做处理,然后显示到视图上面. Adapter有很多种,有ArrayAdapter<T>, BaseA

  • Android ListView自定义Adapter实现仿QQ界面

    PS:listview中有一些简单使用的适配器,如:SimpleAdapter:构造方法SimpleAdapter(Context context,List<Map<String,?>> data,reString [] from,int [] to),但这种适配器过于单调,往往不能达到用户想要的效果,想要随心所欲,就用到了BaseAdapter,自定义适配器. 如图: 1.首先写布局文件 activity_layout.xml <?xml version="1.0

  • Android自定义Adapter的ListView的思路及代码

    在开发中,我们经常使用到ListView这个控件.Android的API也提供了许多创建ListView适配器的快捷方式.例如ArrayAdapter.SimpleAdapter和SimpleCursorAdapter等.但你是否发现,如果采用这些系统自带的适配器,对于事件的响应只能局限在一个行单位.假设一行里面有一个按钮和一个图片控件,它们之间的响应操作是不一样的.若采用系统自带的适配器,就不能精确到每个控件的响应事件.这时,我们一般采取自定义适配器来实现这个比较精确地请求. ListView

  • 揭秘在ListView等AdapterView上动态添加删除项的陷阱

    如何避开在ListView等AdapterView上动态添加删除项的陷阱,下面就为大家分享,具体内容如下 首先,定义如下array资源,作为列表的加载内容: <resources> <string name="app_name">MyListView</string> <string-array name="language"> <item>Java</item> <item>C&l

  • Android listview与adapter详解及实例代码

    一个ListView通常有两个职责. (1)将数据填充到布局. (2)处理用户的选择点击等操作. 第一点很好理解,ListView就是实现这个功能的.第二点也不难做到,在后面的学习中读者会发现,这非常简单. 一个ListView的创建需要3个元素. (1)ListView中的每一列的View. (2)填入View的数据或者图片等. (3)连接数据与ListView的适配器. 也就是说,要使用ListView,首先要了解什么是适配器.适配器是一个连接数据和AdapterView(ListView就

  • ListView Adapter优化 实例

    复制代码 代码如下: //方案一 - adapter优化public class listviewAdapterDemo1 extends BaseAdapter { private String[] mArrData;    private ListView listView;    private AsyncImageLoader asyncImageLoader;    private final LayoutInflater inflater; public listviewAdapte

  • ListView的Adapter使用(绑定数据) 之 自定义每一项的布局去绑定数据

    大家先看第一个例子显示: 这个界面相信大家都看到过的,这次比上一个例子多的是ListView 的每一项绑定的是不再是单纯的一个字符串了,ListView 的每一个条目我们需要显示两个信息,编号和姓名.可以看到,我们绑定了十条数据,用了一个for 循环,每一条绑定的时候创建一个HashMap,然后往里面放数据,放的数据有相对应的key, 即id,name,到时候我们取数据的时候就根据这个key 找到我们放进去的数据,有点类似与键值对的意思,不知道这样解释大家明白不明白. 贴上源代码,然后接下来讲解

  • android开发中ListView与Adapter使用要点介绍

    1. Adapter.getView() public View getView(int position, View convertView , ViewGroup parent){...} 这个方法就是用来获得指定位置要显示的View.官网解释如下: Get a View that displays the data at the specified position in the data set. You can either create a View manually or infl

随机推荐