Andoid 采用ListView三种显示数据列表
Android系统中列表形式的显示方式应该是我们最熟悉不过的界面了,例如通讯录、通话记录、信息列表等等,例如下面的形式:
我们在开发项目需要用到这种形式显示信息时除了调用系统给我们提供的ListView控件以外我们还可以自定义该控件,因为,如果当需要显示复杂的显示列表时系统提供的这种控件不一定能满足我们的需求,在大多数情况下我们可以自定义此控件。
今天给将介绍三种使用ListView的形式:
首先在窗体中添加ListView控件,在代码程序执行时对控件进行初始化:
private ListView list_show; list_show = (ListView) this.findViewById(R.id.list_show);
1. SimpleAdapter适配器:
1 SimpleAdapter spa = new SimpleAdapter(this, data, R.layout.list_item, 2 new String[]{"name","age","id"}, new int[]{R.id.name,R.id.age,R.id.id});
他需要的参数包括:
1.当前上下文对象 Context context,
2.数据资源 List<? extends Map<String, ?>> data,
3. 资源布局文件 int resource,
4.String类型数组的List中数据源数据集合 String[] from,
5.资源文件中控件的id集合 int[] to
在上面代码初始化中我们需要的参数:
List<HashMap<String ,Object>> data = new ArrayList<HashMap<String , Object>>(); for(Student stu : students){ HashMap<String , Object> item = new HashMap<String , Object>(); item.put("name", stu.getName()); item.put("age", stu.getAge()); item.put("id", stu.getId()); data.add(item); }
在此我们需要的数据类型还是上篇代码中的Student类。
我们已经假设students是一个List<Student>类型的集合,在代码中我是通过从SQLite数据库中读取的。经过迭代可以获取到其中的值,最后得到值的集合放入到List<HashMap<String,Object>>中。
第三个参数是资源布局文件,也就是我们写的xml布局文件
1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 2 android:layout_width="fill_parent" 3 android:layout_height="fill_parent" 4 android:orientation="horizontal" > 5 6 <TextView 7 android:layout_width="wrap_content" 8 android:layout_height="wrap_content" 9 android:id="@+id/name" 10 android:paddingLeft="50px" 11 /> 12 13 <TextView 14 android:layout_width="wrap_content" 15 android:layout_height="wrap_content" 16 android:id="@+id/age"
18 android:paddingLeft="50px" 19 /> 20 21 22 23 24 <TextView 25 android:id="@+id/id" 26 android:layout_width="wrap_content" 27 android:layout_height="wrap_content" 28 android:paddingLeft="50px" /> 29 30 </LinearLayout>
最后,设置ListView的适配器:
list_show.setAdapter(spa);
由于界面比较难看,因此在此就不截图给大家展示了,完整的程序已经打包在此共大家下载。
2. SimpleCursorAdapter适配器:
这个适配器与前面那个在名字上即可知道差别,即这个多了一个Cursor,它的数据来源是Cursor类型的:
cursor是从数据库中查询出来的Cursor集合,注意在此不管Cursor数据源来自那儿它都不能被关闭,因为如果cursor.close()以后此对象就不存在,我们也就不能从中读取数据了。
其他参数可以参考上面第一个或IDE中的提示,用法和第一个一样。
SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, R.layout.list_item, cursor, new String[]{"name","age","id"}, new int[]{R.id.name,R.id.age,R.id.id});
最后要记得设置ListView的适配器显示。
3.自定义适配器:
首先需要建立一个适配器类,这个类继承BaseAdapter,他会给我们生成必须的一些实现方法:
具体在下面代码中都已经注释清楚:
1 package com.example.adapter; 2 3 import java.util.List; 4 5 import com.example.sqllite.R; 6 import com.example.sqllite.Student; 7 8 import android.content.Context; 9 import android.view.LayoutInflater; 10 import android.view.View; 11 import android.view.ViewGroup; 12 import android.widget.BaseAdapter; 13 import android.widget.TextView; 14 15 public class StudentAdapter extends BaseAdapter { 16 17 private List<Student> students; //绑定的数据集 18 private int source; //资源文件 19 private LayoutInflater inflater; //布局填充器,Android的内置服务,作用:使用xml文件来生成对应的view对象 20 21 public StudentAdapter(Context context,List<Student> students , int source){ 22 this.students = students; 23 this.source = source; 24 //得到布局填充服务 25 inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 26 } 27 28 public int getCount() { 29 // TODO Auto-generated method stub 30 return students.size(); 31 } 32 33 public Object getItem(int arg0) { 34 // TODO Auto-generated method stub 35 return students.get(arg0); 36 } 37 38 public long getItemId(int arg0) { 39 // TODO Auto-generated method stub 40 return arg0; 41 } 42 43 //取得代表条目的view对象 44 /* (non-Javadoc) 45 * @see android.widget.Adapter#getView(int, android.view.View, android.view.ViewGroup) 46 * arg0 当前条目所要绑定的数据在条目中的索引值 47 * 48 */ 49 public View getView(int arg0, View arg1, ViewGroup arg2) { 50 51 TextView idview = null; 52 TextView nameview = null; 53 TextView ageview = null; 54 55 // TODO Auto-generated method stub 56 //判断是否为第一页 57 //提供缓存机制 58 if(arg1 == null){ 59 //为条目创建View对象,生成条目界面对象 60 arg1 = inflater.inflate(source, null); 61 62 //得到当前条目的数据 63 idview = (TextView)arg1.findViewById(R.id.id); 64 nameview = (TextView)arg1.findViewById(R.id.name); 65 ageview = (TextView)arg1.findViewById(R.id.age); 66 67 ViewCache cache = new ViewCache(); 68 69 cache.id = idview; 70 cache.name = nameview; 71 cache.age = ageview; 72 73 //用视图标识临时存放缓存数据 74 arg1.setTag(cache); 75 } 76 else{ 77 ViewCache cache = (ViewCache)arg1.getTag(); 78 idview = cache.id; 79 nameview = cache.name; 80 ageview = cache.age; 81 } 82 83 //得到当前条目对象 84 Student stu = students.get(arg0); 85 86 //为当前条目赋值 87 idview.setText(stu.getId().toString()); 88 nameview.setText(stu.getName().toString()); 89 ageview.setText(stu.getAge().toString()); 90 91 return arg1; 92 } 93 94 private final class ViewCache{ 95 public TextView id; 96 public TextView name; 97 public TextView age; 98 } 99 100 }
不过在此有一点需要注意,我们用到了缓存,即ListView显示如果超过一整屏幕后出现下拉列表供我们往下拖动查看更多数据,但是它不会每次都生成一个界面View对象,从很大程度上减少了系统开销。关于缓存的使用大家可以查阅更多资料来了解。
编写完了适配器我们就可以使用自定义的适配器来设计我们的ListView的适配器了:
List<Student> students = dbserver.page(0, 15); //从数据库读取数据源 StudentAdapter adapter = new StudentAdapter(this.getApplicationContext(), students, R.layout.list_item); list_show.setAdapter(adapter);
自此,已经可以使用我们自定义的适配器来设计我们的ListView了。
此外,我们通常会编写事件来响应ListView的点击事件,注意是ListView中Item的点击事件,ListView控件其本身也有Click事件:
//绑定条目点击事件 list_show.setOnItemClickListener(new list_listener());
private final class list_listener implements OnItemClickListener{ /* (non-Javadoc) * @see android.widget.AdapterView.OnItemClickListener#onItemClick(android.widget.AdapterView, android.view.View, int, long) * arg0 ListView对象 * arg1 当前所点击的VIew对象 * arg2 当前所点击的条目所绑定的数据在集合中的索引值 * arg3 当前界面中的排列值 */ public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) { // TODO Auto-generated method stub //自定义适配器 ListView lView = (ListView)arg0; Student stu = (Student)lView.getItemAtPosition(arg2); //取得arg2索引对应的条目 Toast.makeText(getApplicationContext(), stu.getId().toString(), 1).show(); /*//利用SimpleCursorAdapter得到的是Cursor对象 Cursor cursor = (Cursor) lView.getItemAtPosition(arg2); int id = cursor.getColumnIndex("_id");*/ } }
为了展示最后我们是成功的,不得不把自己设计的奇臭无比的界面献丑一下:
自此,ListVIew的三种显示数据形式已经完成,大部分时候系统提供的ListView适配器并不能满足我们的需求,我们可以使用自定义的适配器来完成我们的项目。