关键字: Android ListView Header
最近使用OPhone SDK来开发一个应用程序。在使用的过程中,出现了一个问题,个人估计是Ophone底层framework的bug。但是没有底层的支持,苦于没有办法,所以只能自己绕过。
一:ListView Header的使用
在各用控件的使用中,估计ListView是最常用的一个,各种各样的市场都使用ListView来显示数据。但是也有不使用ListView而使用LiearLayout自己向里添加各种组件的(相信这种实现方式的市场的开发人员也不怎么样,会浪费大量的资源,使用更多的内存)。
以“以掌上应用汇”为例:
它在上面显示4个推荐的内容,下面使用一个个ITEM来显示各个应用程序。
使用过ListView开发的人都知道,在ListView外边是不能再嵌套ScrollView的,所以想要头部这种不同的结构显示出来,并且随着ListView的滚动而滚动其实是很简单的。但是网络上有很多种关于这样的讨论,如何的实现,实在不知道为什么。
首先是两种设计:
1,固定的头部,这种头部不随着ListView的滚动而滚动。
就像excel中A,B,C,D,E这样的列名,它们不会随着内容的滚动而滚动。好处当然是可以一直 的指示使用代表的内容是什么意义,坏处是会占用用户的操作空间。
2,不固定的头部,头部不随着ListView的滚动而滚动
就像下图中的,姓名,性别,年龄这样的列名,它他们会随着内容的滚动而变得不可见。它的好处和坏处正好和固定的反过来。
像上面的图中的“以掌上应用汇”的例子,它很明显不能使用固定的头部,因为设备的可视区域本来就小,而且头部占用的空间也多。
两种设计的实现:
1,固定的头部实现起来很简单,把View放在ListView的外边就可以,示例:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical">
<include layout="@layout/fixed_header_view" />
<ListView android:id="@id/android:list" android:layout_width="fill_parent"
android:layout_height="wrap_content" />
<TextView android:id="@id/android:empty"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/empty_msg"/>
</LinearLayout>
2,不固定头部的实现,其实实现起来真的很简单。
在应用程序中把头部inflate出来,然后调用ListView的下面两个方法中的一个就可以(具体请参考API doc)
public void addHeaderView(View v);
public void addHeaderView(View v, Object data, boolean isSelectable);
就可以为ListView添加一个头部,它会随着ListView的滚动而滚动。但是要注意的是
2-1:addHeaderView必须得在setAdapter之前被调用
2-2:在AdapterView.OnItemClickListener的public void onItemClick(AdapterView<?> parent, View view, int position,long id) 中,position中计算header的,就是说,你给ListView的setAdapter的数据会从headerCount开始计数,所以如果你想在自己的Adapter中取数据,你需要减去headerCount。
示例:
// SOME CODE init ListView and setHeader
ListView listView = getListView();
View header = LayoutInflater.from(this).inflate(R.layout.scrolled_header_view, null);
// Do another init to set content for header and add event handler.
listView.addHeaderView(header);
listView.setAdapter(myAdapter);
在响应public void onItemClick(AdapterView<?> parent, View view, int position,long id)时
position -= listView.getHeaderViewsCount(); // 需要减去headerCount
MyItem item = myAdapter.getItem(position);
网络上有关于header使用的介绍,大部分是想在ListView外添加一个ScrollView,可是这样的方案是不可行的。所以就有自己使用ListView来添加各种View来实现,这些View必须被创建出来占用大量的宝贵资源,这样就无法使用ListView的好处,而且代码也不好维护。
像这种只有一个View与其它项目不同的,可以使用header。因为ListView的状态是由系统来维护的,不但能节约代码,方便维护,而且能节约内存的使用。在下一节会介绍多种View在一个ListView中的实现。