ListView在Android中是专门用于显示列表的,是要是View的子类,都可以在ListView中显示出来,它以垂直列表的形式显示所有列表项。每一个条目都是一View对象
ListView生成列表视图有两种方式:
(1)直接使用ListView进行创建
(2)让Activity继承ListActivity(相当于该Activity显示的组件为ListView)
一旦在程序中获得了ListView之后,接下来就需要为ListView设置它要显示的列表项了。在这一点上,ListView显示出AdapterView的特征,通过setAdapter(Adapter)方法为之提供Adapter,并有Adapter提供列表项即可。
Adapter本身只是一个接口,因此我们要用Adapter提供数据的话,就要使用它的实现类。
Adapter常用的实现类如下:
ArrayAdapter:简单,易用的Adapter,通用用于将数组或List集合的多个值包装成多个列表项
SimpleAdapter:它不像它的名字一个简单,它是功能强大的Adapter,可用于将List集合的多个对象包装成多个列表项。
BassAdapter:通常用于被扩展。扩展BaseAdapter可以对各项列表进行最大限度的定制。
Demo如下:
(1): ArrayAdapter: 数组适配器,只能处理一种数据类型。当需要处理一种数据类型的时候可以用ArrayAdapter。它的列表项只能是TextView.
首先定义两个ListView,在activity_main.xml中
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity" >
<ListView
android:id="@+id/list_view1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:divider="#f00" //设置listView的分割符为红色
android:dividerHeight="2px" //设置分隔符高
android:headerDividersEnabled="false" //设置为false,则不在header View之后绘制分隔符
/>
</LinearLayout>
再定义Textview用于显示数据在array_item.xml中
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:id="@+id/tv_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="24dp"
android:padding="10px"
android:shadowDx="4" //设置文本框内文本的阴影在水平方向的偏移
android:shadowDy="4" //在垂直方向的偏移
android:shadowRadius="2" //设置文本框内文本的阴影在模糊程度,该值越大,阴影越模糊
/
</LinearLayout>
最后实现功能在MainActivity.java
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ListView listView1=(ListView) findViewById(R.id.list_view1);
//定义一个数组
String[] arr1 ={"孙悟空","猪八戒","沙僧"};
//将数组包装为ArrayAdapter
ArrayAdapter<String> adapter1 = new ArrayAdapter<String>(this,R.layout.array_item, R.id.tv_view,arr1);
//为ListView设置Adapter
listView1.setAdapter(adapter1);
}
程序运行结果如下:
解释:
new ArrayAdapter<String>(Context context, int resource, int textViewResourceId, String[] objects)
参数:
参数一:context:它代表了访问整个Android应用的接口
参数二: resource: 布局文件的资源id. ListView的每个条目都是一个View对象,则View对象是怎么来的,由布局文件填充而来。
参数三:textViewResourceId:一个资源ID,该资源id代表一TextView,该TextView组件将作为ArrayAdapter的列表项组件,来显示数据。
参数四:objects : 数组或List, 该数组或List将负责为多个列表项提供数据。把要显示的数据放在这里就可以了。
(2)SimpleAdapter: 比ArrayAdapter强大,可以处理多种数据。
1)首先定义ListView在activity_main.xml中
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity" >
<ListView
android:id="@+id/mylist"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
</LinearLayout>
2)定义布局文件simple_item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
<!-- 定义一个ImageView,用于作为列表项的一部分。 -->
<ImageView
android:id="@+id/header"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="10dp"
/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
>
<TextView
android:id="@+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20dp"
android:textColor="#f0f"
android:paddingLeft="10dp"
/>
<TextView
android:id="@+id/desc"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="14dp"
android:paddingLeft="10dp"
/>
</LinearLayout>
</LinearLayout>
3) 实现功能在MainActivity.java
public class MainActivity extends Activity {
private String[] names =new String[]{"虎头", "弄玉", "李清照", "李白"};
private String[] desc=new String[]{"可爱的小孩", "一个擅长音乐的女孩"
, "一个擅长文学的女性", "浪漫主义诗人"};
private int[] imageIds=new int[]{R.drawable.tiger,R.drawable.nongyu,R.drawable.qingzhao,R.drawable.libai};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 创建一个List集合,List集合的元素是Map
List<Map<String, Object>> listItems= new ArrayList<Map<String,Object>>();
for(int i=0;i<names.length;i++){
Map<String, Object> listItem = new HashMap<String, Object>();
listItem.put("header", imageIds[i]);
listItem.put("personName", names[i]);
listItem.put("desc", desc[i]);
listItems.add(listItem);
}
// 创建一个SimpleAdapter 使用simple_item.xml 文件作为列表项组件
SimpleAdapter simpleAdapter = new SimpleAdapter(this, listItems, R.layout.simple_item,
new String[]{"personName","header","desc"},new int[]{R.id.name,R.id.header,R.id.desc});
ListView list= (ListView) findViewById(R.id.mylist);
list.setAdapter(simpleAdapter);
//为listView的列表项的单击事件绑定事件监视器
list.setOnItemClickListener(new OnItemClickListener() {
//第position项被单击时激发该方法
@Override
public void onItemClick(AdapterView<?> parent, View view, int position,long id) {
System.out.println(names[position]+"被单击了");
}
});
// 为ListView的列表项的选中事件绑定事件监听器
list.setOnItemSelectedListener(new OnItemSelectedListener() {
// 第position项被选中时激发该方法
@Override
public void onItemSelected(AdapterView<?> parent, View view,
int position, long id) {
System.out.println(names[position]+ "被选中了");
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
}
}
程序运行如下:
解释:new SimpleAdapter(Context context, List<? extends Map<String, ?>> data, int resource, String[] from, int[] to)
参数一: 见Demo1
参数二: List<? extends Map<String, ?>> data: 该参数应该是一个List<?extends Map<String,?>>类型的集合对象,该集合中每个Map<String,?>对象生成一个列表项。负责提供数据
参数三:该参数指定一个界面布局的的Id 负责提供列表项组件
参数四: 该参数应该是一个String[]类型的参数,该参数决定提取Map<String,?>对象中哪些key对应的value来生成列表项。
参数五:该参数应该是一个int[]类型的参数,该参数巨大填充哪些组件
第5个参数,第4个 参数指定使用id为R.id.name组件显示personName对应的值,是用id为R.id.header显示header对应的值,使用id为R.id.desc 的组件显示desc对应的值。这样第一个列表项组件所包含的三个组件都有了显示内容,后面的每个列表项依次类推。
(3)BaseAdapter:扩展BaseAdapter可以取得对Adapter最大的控制权,程序要创建多少个列表项,每个列表项的组件都由开发者来决定。
1)首先定义ListView在activity_main.xml中
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity" >
<ListView
android:id="@+id/mylist"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
</LinearLayout>
2)实现功能在MainActivity.java
public class MainActivity extends Activity {
private ListView mList;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mList = (ListView) findViewById(R.id.mylist);
BaseAdapter adapter = new BaseAdapter() {
// 重写该方法,该方法返回的View将作为列表项
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// 创建一个LinearLayout,并向其中添加两个组件
LinearLayout line = new LinearLayout(MainActivity.this);
line.setOrientation(0); //水平布局
ImageView image = new ImageView(MainActivity.this);
image.setImageResource(R.drawable.ic_launcher);
TextView text = new TextView(MainActivity.this);
text.setText("第" + (position +1 ) + "个列表项");
text.setTextSize(20);
text.setTextColor(Color.RED);
line.addView(image);
line.addView(text);
// 返回LinearLayout实例
return line;
}
// 重写该方法,该方法的返回值将作为列表项的ID
@Override
public long getItemId(int position) {
return position;
}
@Override
public Object getItem(int position) {
return null;
}
// 指定一共包含40个选项
@Override
public int getCount() {
return 40;
}
};
mList.setAdapter(adapter);
}
}
程序运行结果如下:
解释:扩展BaseAdapter对象需要重写如下4个方法:
getCount(): 该方法的返回值控制该Adapter将会包含多少个列表项,系统调用此方法,用来获知模型层有多少条数据
getItem(int position): 该方法的返回值决定第position处的列表项的内容
getItemId(int position):该方法的返回值决定第 position处的列表项的id.
getView(int position,View convertView,ViewGroup parent):该方法的返回值决定第position出的列表项组件,系统调用此方法,获取要显示至ListView的View对象;
position:本次getView方法调用所返回的View对象,在ListView中处于第几个条目,那么position的值就是多少
屏幕上能显示多少个条目,getView方法就会被调用多少次,屏幕向下滑动时,getView会继续被调用,创建更多的View对象显示至屏幕。
convertView:系统缓存的条目,当有缓存是直接把convertView给View,就不需要填充新的View对象了
ListView的缓存机制:
当条目划出屏幕时,系统会把该条目缓存至内存,当该条目再次进入屏幕,系统在重新调用getView时会把缓存的条目作为convertView参数传入,但是传入的条目不一定是之前被缓存的该条目,即系统有可能在调用getView方法获取第一个条目时,传入任意一个条目的缓存,所有不论是否有缓存,都要重新设置TextView的值。
BaseAdapter: 里面的代码是我们自己写的,进行高度的封装。所以它能完成的功能就比较多,比其它的Adapter。但是如果需求不是很复杂的话,用BaseAdapter的子类是更方便的。