Android精讲--界面编程5(AdapterView及其子类)
列表视图(ListView)和ListActivity
AdapterView
组件是一组重要的组件,AdapterView
本身是一个抽象基类,它派生的子类
在用法上十分相似,只是显示界面有一定的区别,因此本节把它们归为一类,针对它们的共性集中讲解,并突出介绍它们的区别。AdapterView
如下特征。
AdapterView
继承了ViewGroup.它的本质是容器。AdapterView
可以包括多个“列表项”,并将多个“列表项”以合适的形式显示出来。AdapterView
显示的多个“列表项”由Adapter提供。调用AdapterView的setAdapter(Adapter)
方法设置Adapter即可。
AdapterView及其子类的继承关系图
ListView是手机系统中使用非常广泛的一种组件,它以垂直列表的形式显示所有列表项。
创建ListView有如下两种方式。
- 直接使用ListView进行创建。
- 让Activity继承ListActivity(相当于该ActivityM示的组件为ListView)。
一旦在程序中获得了ListView之后,接下来就需要为ListView设置它要思示的列表项了。在这一点上,ListView表显示出AdapterView的特征:通过setAdapter(Adapte)方法为之提供Adapter、并由Adapter提供列表项即可。
ListView、GridView.Spinner,Gallery等AdapterView都只是容器,而Adapter负责提供每个“列表项”组件,AdapterView则负责采用合适的方式显示这些列表项。
# AbsListView常用XML属性
XML属性 相关方法 说明
android:choiceMode 设置AbsListView的选择行为。该属性支持如下属性值。
none:不显示任何选中项
singleChoice:允许单选
multipleChoice:允许多选
multipleChoiceModal:允许多选android:drawSelectorOnTop setDrawSelectorOnTop(boolean) 如果该属性设为true,选中的列表项将会显示在上面
android:fastScrollEnabled 设置是否允许快速滚动。如果该属性设为true,将会显示滚动图标,并允许用户拖动该滚动图标进行快速滚动
android:listSelector setSelector(int) 指定被选中的列表项上绘制的Drawable
android:scrollingCache 如果设为true,该组件在滚动时将会使用绘制缓存
android:smoothScrollbar setSmoothScrollbarEnabled(boolean) 如果设置为false,则不在header View之后绘制分割线
android:stackFromBottom 设置是否从底端开始排列列表项
android:textFilterEnabled 设置是否对列表项进行过滤。当该AbsListView对应的Adapter实现了Filter接口时该属性才会起作用
android:transcriptMode 设置该组件的滚动模式。该属性支持如下属性值。
disable:关闭滚动。这是默认值normal:当该AbsListView受到数据改变通知,且最后一个列表项可见时,该AbsListView将会滚动到底端
alwaysScroll:该AbsListView总会自动滚动到底端
# ListView常用XML属性
XML属性 说明
android:divider 设置List列表项的分隔条(即可用颜色分隔,也可用Drawable分隔)
android:dividerHeight 设置分隔条的高度
android:entries 指定一个数组资源,Android将根据该数组资源来生成ListView
android:footerDividersEnabled 如果设置为false,则不在footer View之前绘制分隔条
android:headerDividersEnabled 如果设置为false,则不在header View之后绘制分隔条
实例:改变分隔条、基于数组的ListView
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <!-- 直接使用数组资源给出列表项 --> <!-- 设置使用红色的分隔条 --> <ListView android:layout_width="fill_parent" android:layout_height="wrap_content" android:entries="@array/books" android:divider="#f00" android:dividerHeight="2px" android:headerDividersEnabled="false"/> </LinearLayout>
上面的界面布局中定义了一个ListView, 并通过android:entries指定了列表项数组,该ListView还通过android:divider
改变了列表项之间的分隔条。
上面第一个ListView指定了android:entries="@array/books"
,该属性值用到了数组资源,因此还需要在应用中定义一个名为books的数组,定义数组的资源文件如下:
<?xml version="1.0" encoding="UTF-8"?> <resources> <string-array name="books"> <item>Java</item> <item>Ajax</item> <item>XML</item> <item>Android</item> </string-array> </resources>
Adapter接口及实现类
Adapter
本身只是一个接口,它派生了ListAdapter
和SpinnerAdapter
两个子接口,其中ListAdapter
为AbsListVlew
提供列表项,而SpinnerAdapter
为AbsSpinner
提供列表项。
Adapter及其子类的继承关系图
#Adapter
常用的实现类如下。
ArrayAdapter
: 简单、易用的Adapter。通常用于将数组或List集合的多个值包装成多个列表项。SimpleAdapter
: 并不简单、功能强大的Adapter.可用于将List集合的多个对象包装成多个列表项。SimpleCursorAdapter
: 与SimpleAdapter
基本相似,只是用于包装Cursor
提供的数据。BaseAdapter
: 通常用于被扩展。扩展BaseAdapter
可以对各列表项进行最大限度的定制。
# 实例:使用 ArrayAdapter创建 ListView
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <!-- 设置使用红色的分隔条 --> <ListView android:id="@+id/list1" android:layout_width="fill_parent" android:layout_height="wrap_content" android:divider="#f00" android:dividerHeight="2px" android:headerDividersEnabled="false" /> <!-- 设置使用绿色的分隔条 --> <ListView android:id="@+id/list2" android:layout_width="fill_parent" android:layout_height="wrap_content" android:divider="#0f0" android:dividerHeight="2px" android:headerDividersEnabled="false" /> </LinearLayout>
上面的布局文件定义了两个ListView,但这两个ListView都没有指定android:entries属性,这意味着它们都需要通过Adapter来提供列表项。
接下来Activity为两个ListView提供Adapter,Adapter决定ListView所显示的列表项。程序如下:
package org.crazyit.ui; import android.app.Activity; import android.os.Bundle; import android.widget.ArrayAdapter; import android.widget.ListView; /** * Description: * <br/>site: <a href="http://www.crazyit.org">crazyit.org</a> * <br/>Copyright (C), 2001-2014, Yeeku.H.Lee * <br/>This program is protected by copyright laws. * <br/>Program Name: * <br/>Date: * @author Yeeku.H.Lee kongyeeku@163.com * @version 1.0 */ public class ArrayAdapterTest extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); ListView list1 = (ListView) findViewById(R.id.list1); // 定义一个数组 String[] arr1 = { "孙悟空", "猪八戒", "牛魔王" }; // 将数组包装ArrayAdapter ArrayAdapter<String> adapter1 = new ArrayAdapter<String> (this, R.layout.array_item, arr1); // 为ListView设置Adapter list1.setAdapter(adapter1); ListView list2 = (ListView) findViewById(R.id.list2); // 定义一个数组 String[] arr2 = { "Java", "Hibernate", "Spring" , "Android" }; // 将数组包装ArrayAdapter ArrayAdapter<String> adapter2 = new ArrayAdapter<String> (this, R.layout.checked_item, arr2); // 为ListView设置Adapter list2.setAdapter(adapter2); } }
通过
ArrayAdapter
实现Adapter
虽然简单、易用,但ArrayAdapter
的功能比较有限。它的每个列表项只能是TextView
。如果开发者需要实现更复杂的列表项,则可以考虑使用SimpleAdapter
,
不要被SimpleAdapter
的名字欺骗,SimpleAdapter
并不简单,而且它的功能非常强大。ListView
的大部分应用场景,都可以通过SimpleAdapter
来提供列表项。
自动完成文本框(AutoCompleteTextView)的功能和用法
自动完成文本框(AutoCompleteTextView)从EditText派生而出,实际上它也是一个文本编辑框,但它比普通编辑框多了一个功能:当用户输入一定字符之后,自动完成文本框会
显示一个下拉菜单,供用户从中选择,当用户选择某个菜单项之后,AutoCompleteTextView按用户选择自动填写该文本框。
网格视图(GridView)功能和用法
GridView用于在界面h按行、列分布的方式来显示多个组件。GridView和ListView有共同的父类:AbsListView,因此GridView和ListView具有很高的相似性,它们都是列表项。
GridView与ListView的唯一区别在于:ListView只显示一列;而GridView可以显示多列。
从这个角度来看,ListView相当于一种特殊的GridView,如果让GridView只显示一列,那么该GridView就变成了ListView。
与ListView类似的是,GridView也需要通过Adapter来提供显示的数据:开发者可以采用上面介绍的4种方式中的任意一种来创建Adapter。不管使用哪种方式, GridView与ListView的用法是基本一致的。
可展开的列表组件(ExpandableListView)
ExpandableListView是ListView的子类,它在普通LislView的基础上进行了扩展,它把应用中的列表项分为几组,每组里又可包含多个列表项。
ExpandableListView的用法与转通ListView的用法非常相似,只是ExpandableListView所显示的列表项应该由ExpandableListAdapter提供。
ExpandableListAdapter及其子类的类图
Spinner的功能和用法
Spinner其实就是一个列表选择框,不过Android的列表选择框并不是需要显示下拉列表的,而是相当于弹出一个菜单供用户选择。
Spinner与Gallery都继承了AbsSpinner,AbsSpinner继承了AdapterView,因此它也表现出AdapterView的特征:只要为AdapterView提供Adapter即可。
画廊视图(Gallery)的功能和用法
Gallery与Spinner组件有共同的父类:AbsSpinner,表明Gallery和Spinner都是一个列表框-它们之间的区别在于Spinner显示的是一个垂直的列表选择框,而Gallery显示的是一个水平的列表选择框。
Gallery与Spinner还有一个区别:Spinner的作用是供用户选择,而Gallery则允许用户通过拖动来査看上—个、下一个列表项。
Android已经不再推荐使用Gallery组件,而是推荐使用其他水平滚动组件。如HorizontalScrollView和ViewPager来代替Gallery组件。因此在新版本的Android平台上应该尽量少用Gallery组件
AdapterViewFlipper的功能与用法
AdapterViewFilpper继承了AdapterViewAnimator,它也会显示Adapter提供的多个View组件,但它每次只能显示一个View组件,程序可通过showPrevious()和showNext()方法控制该组件显示上一个、下—个组件。
AdapterViewFilpper可以在多个View切换过程中使用渐隐渐现的动画效果,除此之外,还可以调用该组件的startFlipping()控制它“自动播放”下一个View组件。
StackView的功能与用法
StackView也是AdapterViewAnimator的子类,它也用于BI2.48使用AdapterViewFlipper显示Adapter提供的系列View。StackView将会以“堆赍实现自动播放图片(Stack)”方式来显示多个列表项,
为了控制StackView显示的View组件,SlackView提供了如下两种控制方式。
- 拖走StackView中处于顶端的View,F+-个View将会显示出来。将上一个View拖进StackView,将使之显示出来。
- 通过调用StackView的showNext〇、showPrevious〇控制显示上一个、上一个组件。