如果程序需要显示不定数量的数据或者是动态变动的数据,比如联系人列表、相册,利用上一节的布局方式来实现将很不灵活,这种场景下最有效的展现视图是列表视图(ListView或Gridview)。Listview和Gridview都继承自AbsListView,所以在使用上有类似的地方。下面具体介绍这两个视图的使用方法。
Listview常用于展示一系列相似类型的数据,下面以一个简化的联系人列表来讲解Listview的基本用法。
主界面布局。
main.xml
1. <RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
2. android:id="@+id/R1"
3. android:layout_width="fill_parent"
4. android:layout_height="fill_parent" >
5. <TextView
6. android:id="@+id/T1"
7. android:layout_width="wrap_content"
8. android:layout_height="wrap_content"
9. android:layout_alignParentTop="true"
10. android:layout_centerHorizontal="true"
11. android:background="#aabbaa"
12. android:text="单击的联系人"/>
13. <ListView
14. android:id="@+id/list"
15. android:layout_width="fill_parent"
16. android:layout_height="wrap_content"
17. android:layout_below="@id/T1" />
18. </RelativeLayout>
主界面采用相对布局,包含2个控件,一个textview,id为T1位于一个顶端,ListView id为listview位于T1下方。T1用于在我们单击listview的item时显示相关内容。
Listview中每个Item的布局界面如下。
Item.xml
1. <?xml version="1.0" encoding="utf-8"?>
2. <RelativeLayout
3. xmlns:android="http://schemas.android.com/apk/res/android"
4. android:layout_width="fill_parent"
5. android:layout_height="wrap_content"
6. android:paddingLeft="10dip">
7. <ImageView
8. android:id="@+id/itemImage"
9. android:layout_width="wrap_content"
10. android:layout_height="fill_parent"/>
11. <TextView
12. android:id="@+id/itemTitle"
13. android:text="名字"
14. android:layout_height="wrap_content"
15. android:layout_width="fill_parent"
16. android:layout_toRightOf="@+id/itemImage"
17. android:textSize="24dip"/>
18. <TextView
19. android:text="电话:"
20. android:layout_height="wrap_content"
21. android:layout_width="fill_parent"
22. android:id="@+id/itemText"
23. android:layout_toRightOf="@+id/itemImage"
24. android:layout_below="@+id/itemTitle"/>
25. </RelativeLayout>
Item也采用相对布局,其中第6行android:paddingLeft="10dip"定义了item显示的内容与屏幕左端留出10个像素的空白区域。在这里itemImage用来显示头像,其右边的itemTitle用来显示名字,itemText在itemTitle下面用来显示电话号码。
最后就是Java的源代码。
MyListView.java
1. import android.app.Activity;
2. import android.content.Context;
3. import android.os.Bundle;
4. import android.view.LayoutInflater;
5. import android.view.View;
6. import android.view.ViewGroup; import android.widget.AdapterView;
7. import android.widget.BaseAdapter;
8. import android.widget.ImageView;
9. import android.widget.ListView;
10. import android.widget.TextView;
11. public class MyListView extends Activity {
12. ListView listView;
13. TextView showinfo;
14. String[] titles={"赵1","钱2","张三","李四","王五"};
15. String[]
texts={"13910000000","13910000001","13910000002","13910000003","13910000004"};
16. int buf=R.drawable.ic_launcher;
17. int[] resIds={buf,buf,buf,buf,buf};
18. @Override
19. public void onCreate(Bundle savedInstanceState) {
20. super.onCreate(savedInstanceState);
21. setContentView(R.layout.main);
22. listView=(ListView)this.findViewById(R.id.list);
23. showinfo=(TextView)this.findViewById(R.id.T1);
24. listView.setAdapter(new MyAdapter(titles,texts,resIds));
25. listView.setOnItemClickListener(new AdapterView.OnItemClickListener(){
26. @Override
27. public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
28. TextView title=(TextView)arg1.findViewById(R.id.itemTitle);
29. String info="单击的联系人是:"+title.getText();
30. TextView text = (TextView) arg1.findViewById(R.id.itemText);
31. info=info+"\n联系电话:"+text.getText();
32. showinfo.setText(info);}
33. });}
34. public class MyAdapter extends BaseAdapter {
35. String[] itemTitles, itemTexts;
36. int[] itemImageRes;
37. public MyAdapter(String[] itemTitles,String[] itemTexts,int[] itemImageRes)
38. {
39. this.itemTitles=itemTitles;
40. this.itemTexts =itemTexts;
41. this.itemImageRes=itemImageRes;
42. }
43. public int getCount() {
44. return itemTitles.length;
45. }
46. public Object getItem(int position) {
47. return itemTitles[position];
48. }
49. public long getItemId(int position) {
50. return position;
51. }
52. public View getView(int position, View convertView, ViewGroup parent) {
53. if (convertView == null)
54. {
55. LayoutInflater inflater =
(LayoutInflater)MyListView.this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
56. View itemView = inflater.inflate(R.layout.item, null);
57. TextView title = (TextView) itemView.findViewById(R.id.itemTitle);
58. title.setText(itemTitles[position]);
59. TextView text = (TextView) itemView.findViewById(R.id.itemText);
60. text.setText(itemTexts[position]);
61. ImageView image = (ImageView) itemView.findViewById(R.id.itemImage);
62. image.setImageResource(itemImageRes[position]);
63. return itemView;
64. } else{
65. TextView title = (TextView) convertView.findViewById(R.id.itemTitle);
66. title.setText(itemTitles[position]);
67. TextView text = (TextView) convertView.findViewById(R.id.itemText);
68. text.setText(itemTexts[position]);
69. ImageView image = (ImageView) convertView.findViewById(R.id.itemImage);
70. image.setImageResource(itemImageRes[position]);
71. return convertView;
72. }}}
73. }
第14~17行我们定义了初始化数据,titles字符串数组是姓名信息、texts字符串数组是手机号信息,resIds整数数组是头像资源drawable里的头像图片id值。在正式项目中数据源我们可以从数据库、文件或网上等地方动态获取。
第22~23行我们获取到主界面main.xml文件里定义的ListView对象和TextView对象。
第24行我们设置了ListView的自定义适配器MyAdapter对象,这个类在第34~71行定义。
第25~32行我们设置了ListView的item单击监听器new AdapterView.OnItemClickListener()。这个监听器的OnItemClick函数在listview的item被单击时调用。参数arg1就是被单击的item的view,所以我们能从arg1获取到里面的itemTitle和itemText信息,并把这部分信息在主界面顶端的textview上显示出来。
第34~71行的MyAdapter继承自BaseAdapter,在其中定义了itemview和需要显示的内容。
第37~42行是MyAdapter的构造函数,我们把传入的itemTitles、itemTexts、itemImageRes保存到对象本地。
下面几行中getCount()、getItem(int position)和getItemId(int position)用于ListView获取item的相关信息。
第52~71行的getView(int position, View convertView, ViewGroup parent)函数被ListView调用来获得具体每个item的View。ListView通过getCount()获取到需要显示的item数量,然后逐个调用getView来获取View并显示。Position参数用于指定需要哪个item,convertView对象告诉adapter是否有item view滑出屏幕后已不在屏幕显示,convertView是可以利旧的view,这样的话就不用因为有1万条记录就要构造1万个item view对象了。
第53行和第64行的if (convertView == null)就是为了利旧itemview,如果convertView存在直接利旧并把convertView里的itemTitle、itemText和itemImage更新后返给listview使用。
第55行和第56行LayoutInflater对象的功能是把一个View的对象与XML布局文件关联并实例化。在这里我们把itemView和item.xml关联并实例化。
第57~62行itemView对象实例化之后,通过findViewById()查找布局文件里的itemTitle、itemText和itemImage,并将数据源里的数据itemTitles[position]、itemTexts[position]和itemImageRes[position]赋值上去。
第63行将itemView返回给listview。
运行效果如图示。