一、回顾一下Android UI里面最基本的视图类继承关系
1、View:View是所有可视的界面元素的基类,所有UI控件(包括布局类)都是有View派生而来的。
2、ViewGroup:View的子类,ViewGroup可以包含多个子视图(View,或者ViewGroup),可以通过扩展ViewGroup类实现复合控件、实现布局管理器(管理所包含的子视图的布局)。
3、AdapterView有如下特征:
a、AdapterView本身是一个抽象基类,AdapterView继承了ViewGroup,本质是容器。
b、AdapterView用来显示多个列表项,这些列表数据由Adapter提供,调用AdapterView的setAdapter(Adapter)方法即可设置。
4、AdapterView及其子类的继承关系如下:
4、ListView和ListActivity
ListView以垂直方式,单行显示所有列表项。
ListView有两种创建方式:直接用ListView创建;通过ListActivity获得
ListView创建完成之后,需要通过setAdapter(Adapter)来设置它要呈现的列表项(从AdapterView中继承而来的特性)。
AbsListView常见的XML属性如下:
ListView常见的XML属性如下:
使用entries属性为ListView指定列表数据是最简单、最直接的方式,下面是一个利用entries指定数据的最简单的ListView例子
/AdapterView/res/layout/activity_main.xml文件:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<ListView
android:id="@+id/listView1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:entries="@array/songs" >
</ListView>
</LinearLayout>
/AdapterView/res/values/AndyLau.xml文件:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="songs">
<item>练习</item>
<item>冰雨</item>
<item>一起走过的日子</item>
<item>天意</item>
<item>谢谢你的爱</item>
</string-array>
</resources>
效果
这种方式下,ListView能自定义的内容就很少了。如果想对ListView的外观、行为进行自定义就需要通过Adapter控制每个列表项的外观和行为。
5、Adapter接口及其实现类
Adapter接口及其实现类的继承关系如下图:
图中用红笔标记的Adapter是较常用的。可以看到几乎所有的Adapter均继承自BaseAdapter,而BaseAdapter同时实现ListAdapter和SpinnerAdapter两个接口,所以BaseAdapter及其子类可同时向AbsListView、AbsSpinner提供列表项。
ArrayAdapter:简单易用的Adapter,用于将数组或者List集合的多个值包装成多个列表项
SimpleAdapter:功能强大的Adapter么可用于将List集合的多个对象包装成多个列表项
SimpleCursorAdapter:SimpleAdapter类似,不用的是用于包装Cursor提供的数据。
下面是使用ArrayAdapter为ListView提供列表项的例子
/AdapterView/res/layout/activity_main_adapter.xml
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<ListView
android:id="@+id/ltv_first"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
</ListView>
<ListView
android:id="@+id/ltv_second"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
</ListView>
<ListView
android:id="@+id/ltv_third"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
</ListView>
</LinearLayout>
/AdapterView/res/layout/list_adapter_source_btn.xml文件
<Button xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/btn_adapter_source"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
/AdapterView/res/layout/list_adapter_source_txt.xml文件
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/txt_adapter_source"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="24dp" />
/AdapterView/res/layout/list_adapter_source_lil.xml文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/lil_adapter_source"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<Button
android:id="@+id/lil_btn_adapter_source"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="null" />
<TextView
android:id="@+id/lil_txt_adapter_source"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:textSize="24dp" />
</LinearLayout>
/AdapterView/src/com/example/adapterview/MainActivity.java文件
package com.example.adapterview;
import android.app.Activity;
import android.os.Bundle;
import android.widget.ArrayAdapter;
import android.widget.ListView;
public class MainActivity extends Activity
{
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_adapter);
ListView ltv_first = (ListView) findViewById(R.id.ltv_first);
String[] songs = { "练习", "冰雨", "一起走过的日子", "天意", "谢谢你的爱" };
//android.widget.ArrayAdapter.ArrayAdapter<String>(Context context, int resource, String[] objects)
//第一个参数:由于涉及到创建组件,所以需要传入Context
//第二个参数,id指定的资源类型必须是TextView及其子类
ArrayAdapter<String> adp_txt = new ArrayAdapter<String>(this,
R.layout.list_adapter_source_txt, songs);
ltv_first.setAdapter(adp_txt);
ListView ltv_second = (ListView) findViewById(R.id.ltv_second);
ArrayAdapter<String> adp_btn = new ArrayAdapter<String>(this,
R.layout.list_adapter_source_btn, songs);
ltv_second.setAdapter(adp_btn);
// java.lang.IllegalStateException: ArrayAdapter requires the
// resource ID to be a TextView
ListView ltv_third = (ListView) findViewById(R.id.ltv_third);
ArrayAdapter<String> adp_lil = new ArrayAdapter<String>(this,
R.layout.list_adapter_source_lil, songs);
ltv_third.setAdapter(adp_lil);
}
}
最后那段代码
ListView ltv_third = (ListView) findViewById(R.id.ltv_third);
ArrayAdapter<String> adp_lil = new ArrayAdapter<String>(this,
R.layout.list_adapter_source_lil, songs);
ltv_third.setAdapter(adp_lil);
加上之后会报错:java.lang.IllegalStateException: ArrayAdapter requires the resource ID to be a TextView
这是因为,ArrayAdapter的只能将TextView及其子类作为列表项加入到ListView中,第三个参数指定的字符串数组中的每个值将依次作为第二个参数指定的TextView(及其子类)的实例(也就是各个列表项)的android:text属性值。注意,Button也是TextView的子类,TextView及其子类的继承关系图如下:
注释掉最后那段出错代码之后,效果如图:
如果程序窗口只需显示一个列表,也可以用ListActivity实现。具体做法不赘述。